Manipulando UILocalNotification quando o aplicativo está ativo

Em Meus minutos, eu uso UILocalNotifications para permitir que os usuários saibam quando eles atingem seu objetivo para uma tarefa. O iOS exibe essas notificações muito bem quando Meus minutos está sendo executado em segundo plano ou quando o telefone está bloqueado.

Mas e quando o aplicativo está ativo?

É certamente um caso extremo, já que não espero que o usuário mantenha o aplicativo ativo quando estiver executando o cronômetro para uma tarefa, mas ainda ocorre e eu quero que o usuário receba o mesmo alerta se atingir uma meta com o aplicativo aberto.

Veja como implementar uma visualização de alerta e um som de notificação para simular o comportamento de um UILocalNotification sendo recebido.

Respondendo a UILocalNotification

Primeiro, adicionei as propriedades UIAlertView e SystemSoundID ao delegado do aplicativo.

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

@property (strong, nonatomic) UIAlertView *notificationAlert;

O alerta de notificação é sintetizado na implementação:

@synthesize notificationAlert = _notificationAlert;

Esteja o aplicativo ativo ou em segundo plano, application: didReceiveLocalNotification: ainda é chamado no delegado do aplicativo, então o código vai lá:

- (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];
}
}

Eu verifico se o aplicativo está ativo. Caso contrário, o usuário será notificado duplamente sobre o mesmo evento, uma vez que já está recebendo o UILocalNotification quando o aplicativo está em segundo plano.

O alerta e o som são carregados lentamente e mantidos, portanto, não são inicializados todas as vezes. Eles podem ser inicializados quando o aplicativo é iniciado, mas optei por não fazer isso para minimizar o tempo de inicialização.

Para usar AudioServicesCreateSystemSoundID, você precisa adicionar AudioToolbox.framework ao seu projeto.

O texto da notificação é usado no alerta. Isso é feito fora da inicialização, pois é dinâmico.

Para o arquivo wav real, encontrei uma coleção de sons que são semelhantes aos sons do sistema iOS padrão aqui .

Por último, o som de notificação é descartado em applicationWillTerminate:

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