2015-04-25 12 views
5

Dodaję dwa przyciski akcji do moich powiadomień push na iOS 8: przycisk Accept i przycisk Deny. Żaden z przycisków nie otworzy aplikacji, ale inne żądania serwera zostaną wykonane w zależności od tego, który przycisk zostanie naciśnięty. Oto moja konfiguracja:iOS 8 przycisków akcji powiadomień push - kod w handleActionWithIdentifier nie zawsze działa, gdy aplikacja jest w tle

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

Następnie w moim metoda delegata, jestem określający działania, które należy podjąć, gdy użytkownik nacisnął jeden z przycisków akcji:

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

Idealnym scenariuszem jest to, że użytkownik nie ma trzeba uruchomić aplikację w całym procesie; naciśnięcie klawisza Accept lub Deny spowoduje wykonanie różnych połączeń z serwerem. Z powyższego kodu, widzę zachowań bardzo niestabilne z działaniami przycisku:

  • Wiele razy, kod programu obsługi akcji nie wykonuje, gdy aplikacja jest w tle i nie ma połączenia serwera są w ogóle ; gdy tak się stanie, jeśli kliknę ikonę mojej aplikacji i uruchomię swoją aplikację, kod obsługi zostanie natychmiast uruchomiony po uruchomieniu aplikacji.
  • Czasami uruchamia się kod obsługi i wszystko działa poprawnie. Żądania serwera są wykonywane, gdy tylko naciśniesz jeden z przycisków akcji.
  • Jeśli umieściłem punkty przerwania w moim Xcode i przejdę przez kod obsługi, wskaźnik sukcesu wynosi również 100%. Nie muszę uruchamiać aplikacji, a kod obsługi zostanie wykonany po naciśnięciu przycisku.

Czy ktoś mógłby mi pomóc wyjaśnić, co powoduje tak niestabilne zachowanie? Z góry dziękuję.

+0

ºHi, czy istnieje możliwość udostępnienia ładunku powiadomienia? Mam kłopoty z ustawianiem przycisków akcji, kiedy nadchodzi zdalne powiadomienie ...>. < –

+0

@SophySwicz w moim kodzie serwera odpowiedni fragment ładunku to 'payloadBuilder.category (" ACTIONABLE ");' Musisz dodać ' ACTIONABLE' category – SeaJelly

+0

Na końcu moja zawartość zakończyła się w następujący sposób: {"aps": {"alert": {"klucz-klucz": "KEY_BODY_ALERT_VOTE_MORNING"}, "category": "NAZWA ACTIO"}} I kiedy ustawiam UIMutableUserNotificationCategory użyj UIUserNotificationActionContextDefault –

Odpowiedz

12

I w końcu zorientowali się, dlaczego. Fakt, że czasami działa, a czasem nie powinien dawać mi wskazówki znacznie wcześniej.

Zgodnie z dokumentacją Apple application:handleActionWithIdentifier:forRemoteNotification:completionHandler::

Implementacja tej metody należy wykonać akcję związaną z podanym identyfikatorem i wykonanie bloku w parametrze completionHandler tak szybko, jak skończysz. Niewykonanie bloku obsługi zakończenia na końcu implementacji spowoduje przerwanie aplikacji.

Wywołuję procedurę obsługi zakończenia na końcu metody application:handleActionWithIdentifier:forRemoteNotification:completionHandler. Jednak fakt, że wysyłam żądania do serwera w moim kodzie obsługi, oznacza, że ​​moja end of implementation nie jest po prostu na końcu tej metody; mój prawdziwy koniec leży w callbacku moich żądań. Sposób, w jaki go koduję, program obsługi zakończenia i wywołanie zwrotne są na dwóch różnych wątkach, a kiedy procedura obsługi kończy się przed osiągnięciem oddzwonienia, to się nie powiedzie.

Rozwiązaniem jest przeniesienie procedury obsługi zakończenia do metod wywołania zwrotnego żądania, tj. Prawdziwego "końca implementacji".Coś takiego:

[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

Na systemów iOS 8 trzeba zadzwonić

[application registerForRemoteNotifications]; 

od application:didRegisterUserNotificationSettings::

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

Już to zrobiłem, przykro mi, że nie wkleiłem tego kodu. Powiadomienia push działają we wszystkich innych scenariuszach, tylko obsługa przycisków akcji powoduje problemy. – SeaJelly

Powiązane problemy