点击本地通知跳转指定DummyViewController失败,求技术解决方案
解决本地通知点击跳转至DummyViewController的正确方法
嘿,我来帮你搞定这个本地通知跳转的问题!你之前在didFinishLaunchingWithOptions里尝试处理,但大概率是没覆盖全场景或者导航控制器的逻辑没处理对。下面分场景给你详细的正确实现方案,兼顾iOS 10前后的版本差异:
一、先搞定基础的通知权限请求
不管哪种场景,第一步必须确保你已经向用户请求了通知权限,不然通知根本弹不出来:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { // 先请求通知权限 if ([[UIDevice currentDevice].systemVersion floatValue] >= 10.0) { UNUserNotificationCenter *notificationCenter = [UNUserNotificationCenter currentNotificationCenter]; notificationCenter.delegate = self; // 别忘设置代理! [notificationCenter requestAuthorizationWithOptions:(UNAuthorizationOptionAlert | UNAuthorizationOptionSound | UNAuthorizationOptionBadge) completionHandler:^(BOOL granted, NSError * _Nullable error) { if (granted && !error) { [[UIApplication sharedApplication] registerForRemoteNotifications]; } }]; } else { UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:(UIUserNotificationTypeAlert | UIUserNotificationTypeSound | UIUserNotificationTypeBadge) categories:nil]; [[UIApplication sharedApplication] registerUserNotificationSettings:settings]; [[UIApplication sharedApplication] registerForRemoteNotifications]; } // 初始化你的窗口和根控制器(这里假设根是导航控制器,根据你的实际情况调整) self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds]; YourRootViewController *rootVC = [[YourRootViewController alloc] init]; UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:rootVC]; self.window.rootViewController = navController; [self.window makeKeyAndVisible]; // 处理从本地通知启动应用的情况 if (launchOptions) { NSDictionary *notificationDict = launchOptions[UIApplicationLaunchOptionsLocalNotificationKey]; if (notificationDict) { [self navigateToDummyVC]; } } return YES; }
二、封装通用的跳转方法
为了避免重复代码,把跳转逻辑抽成一个单独的方法,这样不管哪个场景触发都能复用:
- (void)navigateToDummyVC { DummyViewController *dummyVC = [[DummyViewController alloc] init]; // 根据根控制器类型选择跳转方式,避免崩溃 if ([self.window.rootViewController isKindOfClass:[UINavigationController class]]) { UINavigationController *nav = (UINavigationController *)self.window.rootViewController; [nav pushViewController:dummyVC animated:YES]; } else { [self.window.rootViewController presentViewController:dummyVC animated:YES completion:nil]; } }
三、处理应用在后台/前台时的点击跳转
这里要分iOS版本处理:
iOS 10及以上版本
需要遵守UNUserNotificationCenterDelegate协议,实现两个关键方法:
// 前台收到通知时,控制是否显示弹窗(可选,如果你想前台也弹通知的话) - (void)userNotificationCenter:(UNUserNotificationCenter *)center willPresentNotification:(UNNotification *)notification withCompletionHandler:(void (^)(UNNotificationPresentationOptions))completionHandler { // 允许弹窗和声音 completionHandler(UNNotificationPresentationOptionAlert | UNNotificationPresentationOptionSound); } // 用户点击通知时触发的回调 - (void)userNotificationCenter:(UNUserNotificationCenter *)center didReceiveNotificationResponse:(UNNotificationResponse *)response withCompletionHandler:(void(^)(void))completionHandler { [self navigateToDummyVC]; completionHandler(); // 必须调用这个方法结束回调 }
iOS 10以下版本
直接实现UIApplicationDelegate的旧方法:
- (void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification { // 只有当应用从后台被唤醒或者处于非活跃状态时才跳转 if (application.applicationState == UIApplicationStateInactive || application.applicationState == UIApplicationStateBackground) { [self navigateToDummyVC]; } }
四、常见坑点排查
- 忘记设置代理:iOS10之后如果没给
UNUserNotificationCenter设置delegate,点击通知的回调根本不会触发,这点一定要注意! - 根控制器类型判断错误:如果你的根控制器不是导航控制器,直接调用push会崩溃,所以跳转前一定要判断类型,选择push或者present。
- 未请求权限:如果用户没授权通知权限,通知根本不会显示,自然无法触发跳转,所以权限请求是前提。
内容的提问来源于stack exchange,提问作者iOS Developer
相关产品推荐
相关产品推荐

