最近集成极光推送后需要加一个点击通知栏进行跳转到指定界面的需求问题。因为遇到一些坑,在这里记录一下。
ios的推送不同于安卓。我们的项目在前台、后台、杀死进程的三种情况都能收到通知。归更到底其实就一个问题:如何找到最上层的VC,来进行push操作。(这里我就不赘述极光推送的集成了,可以看官方文档,文档在手,天下我有。)
1.当杀死进程时
这个时候app收到通知了,因为程序已经完全退出了。
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
}
这个方法肯定会走的,相当于重启了你的项目。launchOptions 的是否为nil 可以判断出有没有远程推送。这是知识点,你要知道。
2.在前台或者后台运行程序
这个时候点击消息横栏进来就直接调用极光代理。
以上的两种情况最终我们都会在点击横栏的代理中来处理
// iOS 10 Support---点击通知栏横幅调用
- (void)jpushNotificationCenter:(UNUserNotificationCenter *)center didReceiveNotificationResponse:(UNNotificationResponse *)response withCompletionHandler:(void (^)())completionHandler {
NSDictionary * userInfo = response.notification.request.content.userInfo;
NSLog(@"--推送消息---%@",userInfo);
if([response.notification.request.trigger isKindOfClass:[UNPushNotificationTrigger class]]) {
//则是远程通知---处理远程通知并显示
[JPUSHService handleRemoteNotification:userInfo];
NSLog(@"yuancheng111");
}
[UIApplication sharedApplication].applicationIconBadgeNumber=0;
[JPUSHService resetBadge];//清空JPush服务器中存储的badge值
completionHandler(UIBackgroundFetchResultNewData);
//这里可以根据收到的推送内容来跳转到指定的地方;
[self mastePushViewController:userInfo];
}
// push方法
- (void)mastePushViewController:(NSDictionary *)infoDic{
在这里我们需要进行跳转到指定页面的处理。那么就有一个问题,我们的项目工程里有的页面是presented出来的,那么久无法进行push。那么这里我们就要进行找topVC,并且这个topVC是需要我们进行处理的,是需要具有导航的(navigationController)。
//找当前VC
UIViewController * currentVC = [self getcurrentTopViewController];
NSLog(@"controllerName=%@",NSStringFromClass([currentVC class]));
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.25 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
//跳转到指定页面
[currentVC.navigationController pushViewController:vc animated:YES];
});
}
//找到当前视图控制器
- (UIViewController *)getcurrentTopViewController {
UIViewController *blockViewController = [UIApplication sharedApplication].keyWindow.rootViewController;
while (blockViewController.presentedViewController) {
blockViewController = blockViewController.presentedViewController;
}
if (![blockViewController isKindOfClass:[UITabBarController class]] &&
![blockViewController isKindOfClass:[UINavigationController class]]) {
UIViewController *currentChildVC;
if (blockViewController.childViewControllers.count) {
currentChildVC = blockViewController.childViewControllers.lastObject;
}
while (currentChildVC) {
blockViewController = currentChildVC;
if ([blockViewController isKindOfClass:[UITabBarController class]]) {
blockViewController = [(UITabBarController *)blockViewController selectedViewController];
}
if ([blockViewController isKindOfClass:[UINavigationController class]]) {
blockViewController = [(UINavigationController *)blockViewController topViewController];
}
}
}
if ([blockViewController isKindOfClass:[UITabBarController class]]) {
blockViewController = [(UITabBarController *)blockViewController selectedViewController];
}
if ([blockViewController isKindOfClass:[UINavigationController class]]) {
blockViewController = [(UINavigationController *)blockViewController topViewController];
}
return blockViewController;
}
到这就已经处理了点击通知栏跳转到指定页面的功能。但是我在项目中遇到个比较坑的地方是 当我杀死进程后接受到通知后,点击通知栏打开app,并不能进行跳转。(在前台和app退到后台都没有问题),重新打开app肯定是到首页,我所找到的当前控制器也是,可就是
//跳转到指定页面
[currentVC.navigationController pushViewController:vc animated:YES]; 执行了但是并没有进行跳转。
然后我试了下
UIViewController * currentVC = [self getcurrentTopViewController];
NSLog(@"controllerName=%@",NSStringFromClass([currentVC class]));
self.tabBarController= (UITabBarController *)[UIApplication sharedApplication].delegate.window.rootViewController;
if ([VCStr isEqualToString:@"app主页"]) {
[self.tabBarController.selectedViewController pushViewController:vc animated:YES];
}else{
[currentVC.navigationController pushViewController:vc animated:YES];
}
就可以进行跳转了。我tm就懵逼了。没弄明白是怎么回事(希望有大神能指点)。
需求是完成了,但是作为一个有追求的会写诗的码农,我觉得还是要好好研究下。