iOS: Push-уведомления, UIApplicationStateInactive и быстрое переключение между приложениями.

Согласно Apple Docs, чтобы узнать, нажал ли пользователь на ваше push-уведомление, вы должны проверить applicationState в application:didReceiveRemoteNotification:

Если значение равно UIApplicationStateInactive, пользователь нажал кнопку действия; если значение равно UIApplicationStateActive, приложение было самым передним, когда оно получило уведомление.

Я обнаружил, что это не всегда так. Например:

Дважды нажмите кнопку «Домой», чтобы открыть системный трей и войти в «режим быстрого переключения приложений», ваше приложение перемещается вверх, чтобы показать другие запущенные приложения, и ваше приложение переводится в неактивное состояние (хотя оно все еще остается видимым). Если вы получите push-уведомление в этом режиме, ваш делегат приложения по-прежнему получит application:didReceiveRemoteNotification:, и в этот момент ваш applicationState будет UIApplicationStateActive. Согласно документам, вы должны относиться к этому так, как будто пользователь нажал на предупреждение... но в данном случае это не так. Мало того, пользователь даже не увидел push-уведомление (возможно, потому, что в этом режиме обрезается верх вашего приложения).

Кто-нибудь знает, как определить, что вы находитесь в «режиме быстрого переключения приложений», или правильно обработать уведомление?


person nrj    schedule 09.09.2013    source источник


Ответы (1)


Я смог исправить это сам с помощью нескольких изящных проверок ...

По сути, ключ ко всему этому

-(void)applicationDidEnterBackground:(UIApplication *)application;

Этот метод не вызывается, когда вы входите в быстрое переключение приложений (или центр управления), поэтому вам нужно настроить проверку на его основе.

@property                     BOOL isInBackground;
@property (nonatomic, retain) NSMutableArray *queuedNotifications;

И когда вы получите уведомление...

- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo {
 UIApplicationState appState = application.applicationState;
 // Check if we're in this special state. If so, queue the message up
 if (appState == UIApplicationStateInactive && !self.isInBackground) {
    // This is a special case in which we're in fast app switching or control center
    if (!self.queuedNotifications) {
        self.queuedNotifications = [NSMutableArray array];
    }

    // Queue this to show when we come back
    [self.queuedNotifications addObject:userInfo];
 }
}

А потом, когда мы вернемся...

- (void)applicationDidBecomeActive:(UIApplication *)application {
     application.applicationIconBadgeNumber = 0;


 if (!self.isInBackground) {
    // Show your notifications here

    // Then make sure to reset your array of queued notifications
    self.queuedNotifications = [NSMutableArray array];
 }
}

Еще одна вещь, которую вы, возможно, захотите сделать, — это проверить этот особый случай перехода к быстрому переключению приложений и перехода пользователя куда-то еще. Я делаю это непосредственно перед установкой isInBackground BOOL. Я выбираю отправлять их как локальные уведомления

-(void)applicationDidEnterBackground:(UIApplication *)application {

  for (NSDictionary *eachNotification in self.queuedNotifications) {
     UILocalNotification *notification = [self convertUserInfoToLocalNotification:eachNotification];
     [[UIApplication sharedApplication] scheduleLocalNotification:notification];
 }
 self.queuedNotifications = [NSMutableArray array];
 self.isInBackground = YES;
}
person Eric Busch    schedule 12.11.2014