In the view controller where you fire the local notification:
.h
#import <AVFoundation/AVFoundation.h>
@interface ViewController : UIViewController <AVAudioPlayerDelegate>
@property (nonatomic, strong) AVAudioPlayer *notificationSound;
You don't have to fire a local notification if it enters the background in the app delegate, a local notification will fire regardless if they are in the background or not. didReceiveLocalNotification
is how you handle it when the app is active : From the docs here :
Sent to the delegate when a running app receives a local notification.
.m
-(void)startTimer {
timer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(runTimerTasks:) userInfo:nil repeats:YES];
[self fireLocalNotification];
}
-(void)fireLocalNotification {
UILocalNotification *timerDoneNotification = [[UILocalNotification alloc] init];
timerDoneNotification.fireDate = [NSDate dateWithTimeIntervalSinceNow:secondsLeft];
timerDoneNotification.alertBody = @"Time Up!";
timerDoneNotification.alertAction = @"OK";
timerDoneNotification.timeZone = [NSTimeZone defaultTimeZone];
timerDoneNotification.soundName = @"alarm.aif";
[[UIApplication sharedApplication] scheduleLocalNotification:timerDoneNotification];
}
And then if you just want to play/stop the sound elsewhere like if the secondsLeft is 0 when the app is active you call it as follows :
[self playAlarm];
-(void)playAlarm {
NSBundle *mainBundle = [NSBundle mainBundle];
NSString *filePath = [mainBundle pathForResource:@"alarm" ofType:@"aif"];
NSData *fileData = [NSData dataWithContentsOfFile:filePath];
NSError *error = nil;
self.notificationSound = [[AVAudioPlayer alloc] initWithData:fileData error:&error];
self.notificationSound.numberOfLoops = -1;
[self.notificationSound play];
}
And to stop it:
[self.notificationSound stop];
Downside to this is UILocalNotification sounds can not be longer than 30 seconds but it answers the question at hand.
Reference : UILocalNotification Docs
Points of interest :
When the system delivers a local notification, several things can happen, depending on the app state and the type of notification. If the app is not frontmost and visible, the system displays the alert message, badges the app, and plays a sound—whatever is specified in the notification. If the notification is an alert and the user taps the action button (or, if the device is locked, drags open the action slider), the app is woken up or launched. (If the user taps one of the custom actions you specify using the additionalActions property, the app is woken up or launched into the background.) In its application:didFinishLaunchingWithOptions: method, the app delegate can obtain the UILocalNotification object from the launch options dictionary using the UIApplicationLaunchOptionsLocalNotificationKey key. The delegate can inspect the properties of the notification and, if the notification includes custom data in its userInfo dictionary, it can access that data and process it accordingly. On the other hand, if the local notification only badges the app icon, and the user in response launches the app, the application:didFinishLaunchingWithOptions: method is called, but no UILocalNotification object is included in the options dictionary. When the user selects a custom action, the app delegate’s application:handleActionWithIdentifier:forLocalNotification:completionHandler: method is called to handle the action.
If the app is foremost and visible when the system delivers the notification, the app delegate’s application:didReceiveLocalNotification: is called to process the notification. Use the information in the provided UILocalNotification object to decide what action to take. The system does not display any alerts, badge the app’s icon, or play any sounds when the app is already frontmost.