ldmh5w
Last Updated: July 10, 2018
·
11.54K
· ktusznio

Handling UILocalNotification When App Is Active

In My Minutes I use UILocalNotifications to let users know when they hit their goal for a task. iOS displays these notifications nicely when My Minutes is running in the background or when the phone is locked.

But what about when the app is active?

It's certainly an edge-case since I don't expect the user keep the app active when they are running the timer for a task, but it still occurs and I want the user to get that same heads-up if they hit a goal with the app open.

Here's how to implement an alert view and a notification sound to mimic the behavior of a UILocalNotification being received.

Responding to UILocalNotification

First I added UIAlertView and SystemSoundID properties to the app delegate.

@interface AppDelegate : UIResponder <UIApplicationDelegate> {
    SystemSoundID _notificationSound;
}

@property (strong, nonatomic) UIAlertView *notificationAlert;

The notification alert is synthesized in the implementation:

@synthesize notificationAlert = _notificationAlert;

Whether the app is active or in the background, application:didReceiveLocalNotification: still gets called in the app delegate so the code goes in there:

- (void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification {
    // Play a sound and show an alert only if the application is active, to avoid doubly notifiying the user.
    if ([application applicationState] == UIApplicationStateActive) {
        // Initialize the alert view.
        if (!_notificationAlert) {
            UIAlertView *alert = [[UIAlertView alloc] initWithTitle:nil
                                                            message:nil
                                                           delegate:nil
                                                  cancelButtonTitle:@"Ok"
                                                  otherButtonTitles:nil];
            [self setNotificationAlert:alert];
        }

        // Load the notification sound.
        if (!_notificationSound) {
            NSString *soundPath = [[NSBundle mainBundle] pathForResource:@"Notification"
                                                                  ofType:@"wav"];
            NSURL *soundURL = [NSURL fileURLWithPath:soundPath];
            AudioServicesCreateSystemSoundID((__bridge CFURLRef)soundURL, &_notificationSound);
        }

        // Set the title of the alert with the notification's body.
        [_notificationAlert setTitle:[notification alertBody]];

        // Play the sound and show the alert.
        AudioServicesPlaySystemSound(_notificationSound);
        [alert show];
    }
}

I check whether the app is active. Otherwise the user gets doubly notified of the same event, since they're already receiving the UILocalNotification when the app is in the background.

The alert and sound are lazy-loaded and kept around so they aren't initialized every time. They could be initialized when the app starts but I chose not to do that to minimize startup time.

In order to use AudioServicesCreateSystemSoundID you need to add AudioToolbox.framework to your project.

The text from the notification is used in the alert. That's done outside initialization since it's dynamic.

For the actual wav file, I found a collection of sounds that are similar to standard iOS system sounds here.

Lastly, the notification sound is disposed of in applicationWillTerminate:

- (void)applicationWillTerminate:(UIApplication *)application {
    // Dispose of the notification sound.
    if (_notificationSound) {
        AudioServicesDisposeSystemSoundID(_notificationSound);
    }
}
Say Thanks
Respond

2 Responses
Add your response

3043
660bb878ae25be5b78c87508f64e68f5

two 'my' in link, fyi

over 1 year ago ·
30145

thankyou
Anyway to match the provisioning profile in Xcode's organizer or online developer site with the crazy serial/id number given under Xcode's code signing preferences?

enter image description here

I want to make double sure I am building my app with the correct (Ad Hoc) provisioning profile -- Xcode gives me a long ID (as seen above), but the online developer site and the Xcode preferences that list my provisioning profiles don't list this number.
https://downloader.vip/minecraft-pocket-edition/ https://downloader.vip/counter-strike/ https://bluestacks.vip/

about 1 month ago ·