2015-04-25 7 views
5

Aggiungo due pulsanti di azione alle mie notifiche push su iOS 8: un pulsante Accept e un pulsante Deny. Nessuno dei due pulsanti aprirà l'app, ma verranno richieste richieste server diverse a seconda del pulsante premuto. Qui è la mia messa a punto:Pulsanti di azione di notifica push di iOS 8 - codice in handleActionWithIdentifier non sempre viene eseguito quando l'app è in background

+ (void)requestForPushNotificationToken { 
    UIApplication *application = [UIApplication sharedApplication]; 
    // if ios 8 or greater 
    if ([application respondsToSelector:@selector(registerUserNotificationSettings:)]) { 
     UIMutableUserNotificationAction *acceptAction = [[UIMutableUserNotificationAction alloc] init]; 
     [acceptAction setActivationMode:UIUserNotificationActivationModeBackground]; 
     [acceptAction setTitle:@"Accept"]; 
     [acceptAction setIdentifier:@"ACCEPT_ACTION"]; 
     [acceptAction setDestructive:NO]; 
     [acceptAction setAuthenticationRequired:NO]; 

     UIMutableUserNotificationAction *denyAction = [[UIMutableUserNotificationAction alloc] init]; 
     [denyAction setActivationMode:UIUserNotificationActivationModeBackground]; 
     [denyAction setTitle:@"Deny"]; 
     [denyAction setIdentifier:@"DENY_ACTION"]; 
     [denyAction setDestructive:NO]; 
     [denyAction setAuthenticationRequired:NO]; 

     UIMutableUserNotificationCategory *actionCategory = [[UIMutableUserNotificationCategory alloc] init]; 
     [actionCategory setIdentifier:@"ACTIONABLE"]; 
     [actionCategory setActions:@[acceptAction, denyAction] 
         forContext:UIUserNotificationActionContextDefault]; 

     NSSet *categories = [NSSet setWithObject:actionCategory]; 

     UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:(UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeSound | UIRemoteNotificationTypeAlert) categories:categories]; 
     [application registerUserNotificationSettings:settings]; 
    } else if ([application respondsToSelector:@selector(registerForRemoteNotificationTypes:)]) { // ios 7 or lesser 
     UIRemoteNotificationType myTypes = UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeAlert | UIRemoteNotificationTypeSound; 
     [application registerForRemoteNotificationTypes:myTypes]; 
    } 
} 

Poi, nel mio metodo delegato, sto specificando le azioni da intraprendere quando l'utente preme uno dei pulsanti di azione:

- (void)application:(UIApplication *)application handleActionWithIdentifier:(NSString *)identifier forRemoteNotification:(NSDictionary *)userInfo completionHandler:(void (^)())completionHandler { 
    if ([identifier isEqualToString:@"ACCEPT_ACTION"]) { 
     // Sending a request to the server here 
    } 
    else if ([identifier isEqualToString:@"DENY_ACTION"]) { 
     // Sending a request to the server here 
    } 

    if (completionHandler) { 
     completionHandler(); 
    } 
} 

Lo scenario ideale è che l'utente non lo fa necessità di avviare l'app nell'intero processo; premendo Accept o Deny si effettueranno chiamate diverse al server. Con il codice di cui sopra, sto vedendo i comportamenti molto instabili, con le azioni dei pulsanti:

  • Un sacco di volte, il codice del gestore di azione non esegue quando applicazione è in background e nessuna chiamata di server sono fatti a tutti ; quando ciò accade, se tocco l'icona della mia app e avvio la mia app, il codice del gestore verrà eseguito immediatamente all'avvio dell'app.
  • Occasionalmente, il codice del gestore viene attivato e tutto funziona correttamente. Le richieste del server vengono effettuate non appena premo uno dei pulsanti di azione.
  • Se inserisco i breakpoint nel mio Xcode e passo attraverso il codice del gestore, anche il tasso di successo è 100%. Non è necessario avviare la mia app e il codice del gestore viene eseguito quando si preme il pulsante.

Qualcuno potrebbe aiutarmi a capire cosa sta causando un comportamento così instabile? Grazie in anticipo.

+0

ºCiao, esiste la possibilità di condividere il carico utile della notifica? Ho problemi a impostare i pulsanti di azione quando arriva la notifica remota ...>. < –

+0

@SophySwicz nel mio codice server il pezzo di payload pertinente è 'payloadBuilder.category (" ACTIONABLE ");' Devi aggiungere il ' Categoria 'AZIONABILE' – SeaJelly

+0

Alla fine il mio payload finiva qualcosa del tipo: {"aps": {"alert": {"loc-key": "KEY_BODY_ALERT_VOTE_MORNING"}, "category": "ACTIO NABLE"}} E quando si imposta UIMutableUserNotificationCategory utilizzare UIUserNotificationActionContextDefault –

risposta

12

ho finalmente capito il motivo. Il fatto che a volte funzioni e talvolta non dovrebbe avermi dato il suggerimento molto prima.

Secondo la documentazione di Apple di application:handleActionWithIdentifier:forRemoteNotification:completionHandler::

L'implementazione di questo metodo dovrebbe eseguire l'azione associata con l'identificatore specificato ed eseguire il blocco nel parametro completionHandler non appena si è fatto. La mancata esecuzione del blocco del gestore di completamento alla fine dell'implementazione causerà la chiusura della tua app.

Sto chiamando il gestore di completamento alla fine del metodo application:handleActionWithIdentifier:forRemoteNotification:completionHandler. Tuttavia, il fatto che invii richieste al server nel mio codice gestore significa che il mio end of implementation non è semplicemente alla fine del metodo; la mia vera fine risiede nel richiamo delle mie richieste. Il modo in cui lo codifico, il gestore di completamento e il callback sono su due thread differenti e, quando il gestore di completamento viene eseguito prima che raggiunga la richiamata, fallirà.

Quindi la soluzione è spostare il gestore di completamento nei metodi di callback della richiesta, ovvero la vera "fine dell'implementazione".Qualcosa del genere:

[MyClient sendRequest:userInfo withSuccessBlock:^(id responseObject){ 
    NSLog(@"Accept - Success"); 
    if (completionHandler) { 
     completionHandler(); 
    } 
} withFailureBlock:^(NSError *error, NSString *responseString) { 
    NSLog(@"Accept - Failure: %@",[error description]); 
    if (completionHandler) { 
     completionHandler(); 
    } 
}]; 
0

Su iOS 8 è necessario chiamare

[application registerForRemoteNotifications]; 

da application:didRegisterUserNotificationSettings::

- (void)application:(UIApplication *)application didRegisterUserNotificationSettings:(UIUserNotificationSettings *)notificationSettings { 
    [application registerForRemoteNotifications]; 
} 
+0

L'ho già fatto, mi dispiace non averlo incollato in quel codice. La notifica push funziona in tutti gli altri scenari, solo i gestori di pulsanti azione hanno problemi. – SeaJelly

Problemi correlati