您的位置:首页 > 移动开发

iOS推送消息启动页面,URL启动App并跳转页面设计

2016-09-10 10:27 525 查看

需求描述:

App里经常使用推送消息通知用户,如果不做任何操作,只给将App启动起来,这样没有任何效果,最佳实践是启动起来App后,自动拉起指定的页面,最好再有参数传递,通过参数来将数据加载到该页面上。
使用场景:
1. App推送订单消息后,点击消息,启动App,跳转到订单详情页
2. App推送聊天信息,点击消息后,启动App,跳转到聊天页面
3. 分享出去的页面里带有链接,点击该链接后,启动App,跳转到目标页面。

设计原理:

1. App启动数据传递
iOS里方法application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 里的launchOptions表示是的App启动时传递的数据。如果App后台已经死掉,推送消息过来后,会先拉起App,推送消息里的数据会通过launchOptions传递过来。
2. 后台App接收推送后数据传递
iOS AppDelegate里的application didReceiveRemoteNotification:(NSDictionary *)userInfo方法表示App在后台运行时,如果有推送,点击推送消息拉起App后通过userInfo传递数据。
3. NSURL启动App传递数据
AppDeletage中的application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation方法表示,当系统里打开某URL后,系统查询该URL是否有App注册,如果发现有App注册该URL的Scheme,则拉起该App,并将url传递过去。
# 通过上述三个delegate可以实现前面的需求场景。

实现:

通过上述三种方法可以将推送数据或URL数据拿到,但是拿到后我们需要跳转到指定页面。假如我们将要做的跳转操作称为Action,我们定义Aciton的格式如下:action:   wenxiaoyou://ACTION_NAME?param1=value1¶m2=value2
上述wenxiaoyou表示该操作的scheme用来区分其它的App注册的模式,一定要保证该scheme和别的App不一样,否则会拉错App。推荐使用App的包名。ACTION_NAME:表示你做的操作,一般我们打开App有很多操作,比如我们的App做留学一对一名校导师咨询的,有打开订单,导师首页,导师服务首页,导师评论页===param1=value1:表示要传递的参数,如果是订单,可以使用类似:wenxiaoyou://order_detail?order_id=1234,表示要打开订单详情页,该页面显示的是订单号为1234的内容。
如果将App的scheme注册到系统中呢?打开Info.plist里添加scheme注册项:URL types   > URL Schemes      > Document Role : Editor      > URL identifier : com.wenxiaoyou.com      > URL Schemes:    wenxiaoyou
通过上面的操作即可添加scheme项。

// 实现App启动数据传递处理- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {...#pragma mark- 处理启动时的推送通知    NSDictionary* pushInfo = [launchOptions objectForKey:UIApplicationLaunchOptionsRemoteNotificationKey];    if(pushInfo){//推送信息        [self parsePushNotifaction:pushInfo];    }
...}
// 后台推送数据传递处理- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo{    NSLog(@"后台推送消息");    [self parsePushNotifaction:userInfo];}

// Web跳转处理一并处理
- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString*)sourceApplication annotation:(id)annotation{        NSString* action = [NSString stringWithFormat:@"%@://%@?%@", url.sheme, url.host, url.query];        NSMutableDictionary* dic = [[NSMutableDictionary alloc]init];        [dic setObject:action forKey:KEY_ACTION];        // 保存起来要执行的任务        SAVE_TO_USER_DEFAULT(dic, KEY_BOOT_TASK);        [[NSNotificationCenter defaultCenter] postNotificationName:PUSH_MSG_BOOT_TASK_NOTIFICATION object:niluserInfo:dic];}
// 推送消息处理-(void)parsePushNotifaction:(NSDictionary *)pushInfo{    SAVE_TO_USER_DEFAULT(pushInfo, KEY_BOOT_TASK);    [[NSNotificationCenter defaultCenter] postNotificationName:PUSH_MSG_BOOT_TASK_NOTIFICATION object:niluserInfo:pushInfo];

}
# SAVE_TO_USER_DEFAULT表示将推送内容及Web跳转信息保存到沙盒里。为什么要这么做???因为App收到推送时无非两种情况下:1. App未启动 2. App已经启动如果App未启动,当收到推送并点击推送信息时,会打开App,通过didFinishLaunchingWithOptions方法获得到推送内容。但是我们无法执行页面的跳转,因为在AppDelegate里还没有启动我们的“首页”,如果你直接打开目标页面也不是不可,但是目标页面如果点击返回,如何处理?所以,个人认为最好的方式就是先打开App的首页,然后再通过首页再push到目标页面,这样用户点击返回时,也会返回App首页。Ok,既然我们需要打开App首页,那我们推送里的跳转操作Action就需要暂时suspend起来,然后等App首页启动起来之后,再将suspend的Action启动起来。所以我们要将Action保存到沙盒里,等待首页启动起来之后,再执行suspend的Action。
#为什么要使用通知Notification??因为parsePushNotifaction被调用了两次,一次是在App启动时,另外一次是在App已经启动时,当到Push消息后,我们可以直接实现跳转。为什么不直接在parsePushNotifaction里执行跳转呢??因为VC的启动与跳转都需要基于一个NaviController,而我们在AppDelegate里无法确定当前是哪个NaviController,虽然我们可以保存当前的NaviController。但是我还是希望使用下面这种方式,大家可以基于此展开讨论。
我们的项目里所有VC都继承自BaseViewController,这个基类在init的时候,我们注册了PUSH_MSG_BOOT_TASK_NOTIFICATION通知的接收。这样,当前App里所有的页面都可以接收到要跳转Action的通知,但是,我们设定了,只有当前正在显示的VC才执行跳转,其它压栈的VC不执行跳转。伪代码如下:
BaseViewController{ init(){    // 注册PUSH_MSG_BOOT_TASK_NOTIFICATION通知onBootActionNotify() }

 void onBootActionNotify(Notify* notifyInfo){     // 如果当前VC不是最前端显示的VC,直接返回     if(!self.isVisiable){        return ;     }          // 如果Action已经被消费处理,则删除KEY_BOOT_TASK     REMOVE_USER_DEFAULT(KEY_BOOT_TASK);
     // 如果当前App在后台运行,则将跳转操作放到Block里,等待App重新回到前台后自动执行该Block     if(App.isInBackground){       App.backBootBLock = {           // 解析notifyInfo,并执行跳转       };     }else{           // 解析notifyInfo,并执行跳转            } }}
# 为了实现上述的后台重新唤醒后,自动执行跳转,需要在AppDelegate里添加Delegate-(void)applicationDidBecomeActive:(UIApplication *)application{    APP.isInBackground = NO;    if(App.backBootBlock){       App.backBootBlock();    }}
-(void)applicationDidEnterBackground:(UIApplication *)application{    APP.isInBackground = YES;}

# OK,上述代码写完,好像没有问题了,仔细看下,好像首页启动后suspendAction的处理还没有添加。伪代码如下:HomeViewController{  init(){
    // 如果因为推送或openURL启动了App,会有挂起的Action处理,这个时候可以处理它了。    NSDictionary* notifyInfo = GET_OBJ_FROM_USER_DEFAULT(KEY_BOOT_TASK);    if(notifyInfo != nil){        [[NSNotificationCenter defaultCenter] postNotificationName:PUSH_MSG_BOOT_TASK_NOTIFICATION object:niluserInfo:notifyInfo];    }
  }}

以上
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: