DidReceiveRemoteNotification: fetchCompletionHandler: открыть из значка против push-уведомления
Я пытаюсь выполнить обработку уведомлений фонового push, но у меня возникают проблемы с определением того, открыл ли пользователь приложение из push-уведомления, которое было отправлено, а не открывало его из значка.
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler {
//************************************************************
// I only want this called if the user opened from swiping the push notification.
// Otherwise I just want to update the local model
//************************************************************
if(applicationState != UIApplicationStateActive) {
MPOOpenViewController *openVc = [[MPOOpenViewController alloc] init];
[self.navigationController pushViewController:openVc animated:NO];
} else {
///Update local model
}
completionHandler(UIBackgroundFetchResultNewData);
}
С помощью этого кода приложение открывается в MPOOpenViewController независимо от того, как пользователь открывает приложение. Как я могу сделать это так, чтобы контроллер представления был нажат только в том случае, если они открывают приложение для прокрутки уведомления?
С тем же кодом это работало на iOS 6, но с новым методом iOS 7, он не ведет себя так, как я хочу.
Изменить: Сейчас я пытаюсь запустить приложение на iOS 7, и мы не поддерживаем какую-либо версию до iOS 7. Я использовал тот же самый точный код в версии iOS 6 (без обработчика завершения), и он вел себя так, как я ожидал. Вы проведете уведомление, и это будет вызвано. Если вы открыли из значка, метод никогда не будет вызываться.
Ответы
Ответ 1
Хорошо, я понял это. Метод фактически вызывается дважды (один раз, когда он получает push, и один раз, когда пользователь взаимодействует со значком или уведомлением).
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler {
if(application.applicationState == UIApplicationStateInactive) {
NSLog(@"Inactive");
//Show the view with the content of the push
completionHandler(UIBackgroundFetchResultNewData);
} else if (application.applicationState == UIApplicationStateBackground) {
NSLog(@"Background");
//Refresh the local model
completionHandler(UIBackgroundFetchResultNewData);
} else {
NSLog(@"Active");
//Show an in-app banner
completionHandler(UIBackgroundFetchResultNewData);
}
}
Спасибо Tim Castelijns за следующее дополнение:
Примечание: причина, по которой он дважды вызван, связан с полезной нагрузкой, имеющей content_available : 1
. Если вы удалите ключ и его значение, он будет работать только при нажатии. Это не решит проблему, так как некоторым людям нужен этот ключ, чтобы быть правдой.
Ответ 2
Решение @MikeV в Swift 2:
func application(application: UIApplication, didReceiveRemoteNotification userInfo: [NSObject : AnyObject], fetchCompletionHandler completionHandler: (UIBackgroundFetchResult) -> Void) {
if(application.applicationState == UIApplicationState.Inactive)
{
print("Inactive")
//Show the view with the content of the push
completionHandler(.NewData)
}else if (application.applicationState == UIApplicationState.Background){
print("Background")
//Refresh the local model
completionHandler(.NewData)
}else{
print("Active")
//Show an in-app banner
completionHandler(.NewData)
}
}
Ответ 3
Решение @MikeV в Swift 3 (но с оператором switch):
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
switch application.applicationState {
case .inactive:
print("Inactive")
//Show the view with the content of the push
completionHandler(.newData)
case .background:
print("Background")
//Refresh the local model
completionHandler(.newData)
case .active:
print("Active")
//Show an in-app banner
completionHandler(.newData)
}
}