YongSir

专业程序员伪装者

APNs及跳转处理

APNs

最近app加上了apns,在客户端的操作主要在于执行对应的操作,这里涉及几种不同的情况
PS: 其实配置证书方面也有一些变动,还有Xcode中项目的设置上,不过这些都是公开资料,google之

当设备接到apns发来的通知,应用处理通知有以下几种情况:

  • 接收状况

    • 应用还没有加载

      这时如果点击通知的显示按钮,会调用didFinishLaunchingWithOptions,不会调用didReceiveRemoteNotification方法。
      如果点击通知的关闭按钮,再点击应用,只会调用didFinishLaunchingWithOptions方法。

    • 应用在前台(foreground)

      这时如果收到通知,会触发didReceiveRemoteNotification方法

    • 应用在后台

      1. 此时如果收到通知,点击显示按钮,会调用didReceiveRemoteNotification方法。
      2. 点击关闭再点击应用,则上面两个方法都不会被调用这时,只能在applicationWillEnterForeground或者applicationDidBecomeActive,根据发过来通知中的badge进行判断是否有通知,然后发请求获取数据
  • 对应处理

首先是一个跳转的问题,在对应的地方如何跳转到对应的控制器呢?

其实iOS中作为控制器管理的控制器只有两种:NagVCTabVC两种,只要找到了root,跳转就很easy了,必入可以这样简单的实现:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34

- (void)jumpVCThroughAPNsWith: (NSString *)type {

// 先获取rootVC类型
UIViewController * root = (UIViewController*)self.window.rootViewController;
if ([root isKindOfClass:[UITabBarController class]]){
CustomTabBarController *tabbarController = (CustomTabBarController *)root;

if ([type isEqualToString:@"gift_page"]) {
tabbarController.selectedIndex = 3;
UINavigationController *navController = (UINavigationController *)[tabbarController selectedViewController];

ZXGiftManagerViewController *giftVC = [[UIStoryboard storyboardWithName:@"ZXMyProfileTableView" bundle:nil] instantiateViewControllerWithIdentifier:@"ZXGiftmanager"];

giftVC.hidesBottomBarWhenPushed = YES;
giftVC.urlStr = @"/index.php?c=salectrl&m=get_manage_card_data";
[navController pushViewController:giftVC animated:YES];
} else if([type isEqualToString:@"course_page"]){

tabbarController.selectedIndex = 2;
UINavigationController *navController = (UINavigationController *)[tabbarController selectedViewController];

LessonNewDetailViewController * lessonDCon = [[LessonNewDetailViewController alloc]init];
lessonDCon.reqUrl = [NSString stringWithFormat:@"%@/index.php?c=course_ctrl&m=course_data&id=%@",WEB_URL,self.zxMsg.urlStr];
[navController pushViewController:lessonDCon animated:YES];
} else if([type isEqualToString:@"webview_full"]) {

tabbarController.selectedIndex = 0;
UINavigationController *navController = (UINavigationController *)[tabbarController selectedViewController];
SaleViewController * webViewCon =[[SaleViewController alloc]init];
webViewCon.webNewUrl = [NSString stringWithFormat:@"http://host.../index.php?c=fast_show_ctrl&m=show_book_free&id=%@&hide_cache=1",self.zxMsg.urlStr];
[navController pushViewController:webViewCon animated:YES];
}
}

这里根据APNS发过来的typekey执行不同的跳转:

1
2
3
4
5
6
7
8
9
{
"aps": {
"alert":"Hello Push!",
"badge":1,
"sound":"default"
"type" : "xxxx"
},
"page":"home"
}

对应:

type VC
“gift_page” ZXGiftManagerViewController
“course_page” LessonNewDetailViewController
“webview_full” SaleViewController

这里只是一个最简单最方便的实现方式,前提是你知道到底跳转到哪儿

但还有更变态的情况,比如你的app基本都是用的webVC,其实是真的有在页面之间的随意非正常跳转的需求的,所以建议专门写一个RoutingManage类用来管理所有的非正常跳转,通过Runtime根据传过来的用来创建ViewControllerName创建VC,再由一个root去跳转

比如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
- (void)jumpVCThroughAPNsWith: (NSDictionary *)info {
{
// 拿到类名
NSString *class =[NSString stringWithFormat:@"%@", info[@"viewControllerName"]];
const char *VCClassName = [class cStringUsingEncoding:NSASCIIStringEncoding];

// 创建并注册类
Class newClass = objc_getClass(VCClassName);
if (!newClass)
{
Class superClass = [NSObject class];
newClass = objc_allocateClassPair(superClass, VCClassName, 0);
objc_registerClassPair(newClass);
}

// 创建对象
id instance = [[newClass alloc] init];

// 获取导航控制器
UITabBarController *tabVC = (UITabBarController *)self.window.rootViewController;
UINavigationController *pushClassStance = (UINavigationController *)tabVC.viewControllers[tabVC.selectedIndex];

// 跳转
[pushClassStance pushViewController:instance animated:YES];
}

这一点在你的app有大量的webVC,基本没什么本地VC的时候,显得尤其重要,比如我司app上一个版本就是这种情况

ok,祝你跳跳愉快了 …🤓