iOS点击推送通知跳转页面

3,522 阅读2分钟

iOS的推送通知,除了带有title和content这些明文字段外,还可以夹带一些自定义参数。使用这些参数,我们就可以判断需要打开什么页面,传递什么参数,这是我们实现点击推送通知跳转页面的技术基础。 当用户接受到推送通知并点击后,系统会自动打开App。而推送的自定义参数,会包含在

(BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions

函数的launchOptions中。launchOptions是一个字典,包含了App启动的一些参数,而推送的自定义参数藏在了名为“UIApplicationLaunchOptionsRemoteNotificationKey”的键中。拿到了推送参数后,通过NSNotificationCenter发送系统通知,将“我已拿到推送自定义参数”的消息发送出去。

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
      NSDictionary *userInfo = launchOptions[UIApplicationLaunchOptionsRemoteNotificationKey];
    if (userInfo) {
        [self performSelector:@selector(postNotification:) withObject:userInfo];
    }
}

既然发送了通知,很明显我们还需要一个通知接受方来处理通知。一般我们会选择根控制器来处理推送切换页面,因为App无论在什么页面,跟控制器都会在栈里,随时可以响应页面切换的事件。在自定义的tabbarController中,添加通知接收方法。

@interface DBTabBarController : UITabBarController
@end
- (void)viewDidLoad {
  [super viewDidLoad];
  [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(userInfoNotification:) name:@"userInfoNotification" object:nil];
}

- (void)userInfoNotification:(NSNotification *)notification {
  NSDictionary *dic = notification.userInfo;
  ......
}

推送自定义参数就在notification.userInfo中,你可以根据你们之前定好的规则来切换页面。比如我们的项目中有一个type参数,决定具体切换的VC,一个messageId,如果type是message,则切换到系统消息详细页面,该页面需要一个messageId来获取具体到消息内容。

至于这个自定义参数在那里填写,相信很多中小型公司的推送都由第三方服务商提供。我就拿我们用的友盟来举例。

友盟推送

但是当我们实机去测试的时候,往往会发现还是有几率不能实现跳转,尤其是第一次打开App的时候(冷启动)。这是由于

(BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions

这个方法在执行的时候,我们的TabbarController还没有初始化好,所以全局消息发出去了,但接受者还没有,自然是无法顺利处理我们的任务。解决方法是延迟执行发送消息的方法,我设定的时间戳是0.5秒,0.5秒后根控制器基本都处理好了,自然不会出现这个问题了。

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    NSDictionary *userInfo = launchOptions[UIApplicationLaunchOptionsRemoteNotificationKey];
    if (userInfo) {
        [self performSelector:@selector(postNotification:) withObject:userInfo afterDelay:0.5];
    }
    return YES;
}