美文网首页自鉴iOS学习征服iOS
消息推送---跳转到指定页面

消息推送---跳转到指定页面

作者: 墨痕未干 | 来源:发表于2017-02-16 16:21 被阅读301次

    最近在弄友盟推送,点击推送的消息,打开App,不管在哪个页面都要跳转对应的页面。其中在跳转对应的页面这块卡了,在这里记录一下自己的解决方法,不是最好的。希望有更好的方法或者思路可以留言。

    友盟推送设置

    AppDelegate.m文件里:
    /*
     ** 友盟推送
     */
    - (BOOL)application:(UIApplication *)application willFinishLaunchingWithOptions:(nullable NSDictionary *)launchOptions{
        
        [UMessage startWithAppkey:@"你的Appkey" launchOptions:launchOptions];
        [UMessage registerForRemoteNotifications];
        
        UIMutableUserNotificationAction *action1 = [[UIMutableUserNotificationAction alloc] init];
        action1.identifier = @"action1_identifier";
        action1.title=@"Accept";
        action1.activationMode = UIUserNotificationActivationModeForeground;//当点击的时候启动程序
        
        UIMutableUserNotificationAction *action2 = [[UIMutableUserNotificationAction alloc] init];  //第二按钮
        action2.identifier = @"action2_identifier";
        action2.title=@"Reject";
        action2.activationMode = UIUserNotificationActivationModeBackground;//当点击的时候不启动程序,在后台处理
        action2.authenticationRequired = YES;//需要解锁才能处理,如果action.activationMode = UIUserNotificationActivationModeForeground;则这个属性被忽略;
        action2.destructive = YES;
        
        UIMutableUserNotificationCategory *actionCategory = [[UIMutableUserNotificationCategory alloc] init];
        actionCategory.identifier = @"category1";//这组动作的唯一标示
        [actionCategory setActions:@[action1,action2] forContext:(UIUserNotificationActionContextDefault)];
        
        NSSet *categories = [NSSet setWithObject:actionCategory];
        
        //如果默认使用角标,文字和声音全部打开,请用下面的方法
        [UMessage registerForRemoteNotifications:categories];
        NSLog(@"------友盟推送设置------");
        
       // [UMessage setLogEnabled:YES];
        return YES;
    }
    

    获取Device Token用来测试模式

    AppDelegate.m文件里:
    
    /**
     *
     *  获取Device Token
     *  @param application
     *  @param deviceToken
     */
    - (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken{
    
        NSLog(@"------Device Token:%@",[[[[deviceToken description] stringByReplacingOccurrencesOfString: @"<" withString: @""]                  stringByReplacingOccurrencesOfString: @">" withString: @""]                 stringByReplacingOccurrencesOfString: @" " withString: @""]);
        
    }
    

    收到推送消息的三种情况:

    AppDelegate.m文件里:
    
    /**
     * 接收推送来的数据并作对应处理
     */
    - (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo
    {
        self.userInfo = userInfo;
        //关闭友盟自带的弹出框
        [UMessage setAutoAlert:NO];
        [UMessage didReceiveRemoteNotification:userInfo];
        NSString* alert=[userInfo[@"aps"] valueForKey:@"alert"];
        
        NSLog(@"-------推送的数据-------%@",userInfo);
        
        //定制自定的的弹出框
        if([UIApplication sharedApplication].applicationState == UIApplicationStateActive)//App是打开状态
        {
            UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"大料爆料"
                                                                message:alert
                                                               delegate:self
                                                      cancelButtonTitle:@"朕去看看"
                                                      otherButtonTitles:@"朕知道啦",nil];
            [alertView show];
        }else{
            
            [[NSNotificationCenter defaultCenter] postNotificationName:@"userInfoNotification" object:self userInfo:self.userInfo];
        }
    }
    

    第一种

    App是关闭的,点击推送消息直接唤醒App。然后跳转指定页面,这种情况简单,在首页直接加个通知,打开就行。这种情况进来App肯定在首页,好处理。

    第二种

    App是在后台运行的,你唤醒App之后,不确定是哪个页面。初步想法是在每个页面都加上通知,用来接收消息。这里有个方法可以统一加通知:

    我的项目是自定义NavigationController,在LeoNavigationController.m中加上代码:

    //每个push进来的ViewController都会走这个方法,这样就能统一给ViewController加上通知
    
    -(void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated{
    
    //给每个push进来的控制器加通知
    
    [viewController gettingNotification];
    
    }
    

    gettingNotification这个方法我写在了viewController得扩展里:

    #import "UIViewController+catagory.h"
    #import "MoreInforViewController.h"
    
    static NSInteger leo = 0;
    @implementation UIViewController (catagory)
    
    -(void)gettingNotification{
        
        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(userInfoNotification:) name:@"userInfoNotification" object:nil];
        leo = 0;
        NSLog(@"--------设置接受通知--------");
    }
    
    -(void)userInfoNotification:(NSNotification*)notification{
        
        if (leo == 0) {
            
            NSDictionary *dict = [notification userInfo];
            NSLog(@"-----推送通知来的数据-----:%@",dict);
            NSString* url=[dict valueForKey:@"url"];
            
            NSString* type=[[NSString alloc]init];
            type = [dict valueForKey:@"type"];
            if (type == nil) {
                type = @"stroy";
            }
            NSLog(@"-----推送通知来的数据-----:%@",type);
            if ([type isEqualToString:@"stroy"]) {
                
                NSLog(@"-----加载推送来的链接-----:%@",url);
                MoreInforViewController* vc = [[MoreInforViewController alloc]init];
                vc.url = url;
                [[self getCurrentVC].navigationController pushViewController:vc animated:YES];
                leo++;
            }  
        }
    }
    
    /**
     *  获取当前的屏幕展示的控制器
     *
     *  @return 控制器
     */
    
    - (UIViewController *)getCurrentVC{
        
        UIViewController *result = nil;
        UIWindow * window = [[UIApplication sharedApplication] keyWindow];
        //app默认windowLevel是UIWindowLevelNormal,如果不是,找到UIWindowLevelNormal的
        if (window.windowLevel != UIWindowLevelNormal)
        {
            NSArray *windows = [[UIApplication sharedApplication] windows];
            for(UIWindow * tmpWin in windows)
            {
                if (tmpWin.windowLevel == UIWindowLevelNormal)
                {
                    window = tmpWin;
                    break;
                }
            }
        }
        id  nextResponder = nil;
        UIViewController *appRootVC=window.rootViewController;
        //    如果是present上来的appRootVC.presentedViewController 不为nil
        if (appRootVC.presentedViewController) {
            nextResponder = appRootVC.presentedViewController;
        }else{
            UIView *frontView = [[window subviews] objectAtIndex:0];
            nextResponder = [frontView nextResponder];
            //<span style="font-family: Arial, Helvetica, sans-serif;">//  这方法下面有详解    </span>
        }
        
        if ([nextResponder isKindOfClass:[UITabBarController class]]){
            UITabBarController * tabbar = (UITabBarController *)nextResponder;
            UINavigationController * nav = (UINavigationController *)tabbar.viewControllers[tabbar.selectedIndex];
            //UINavigationController * nav = tabbar.selectedViewController ; 上下两种写法都行
            result=nav.childViewControllers.lastObject;
            
        }else if ([nextResponder isKindOfClass:[UINavigationController class]]){
            UIViewController * nav = (UIViewController *)nextResponder;
            result = nav.childViewControllers.lastObject;
        }else{
            result = nextResponder;
        }
        NSLog(@"------当前展示的控制器------%@",result);
        return result;
    }
    

    这里有两个坑~
    刚开始,我只是把所有的界面都注册通知了,然后推送消息,发现你打开过的控制器,都会push你要推送的那个页面。后来我想方法获取了当前屏幕展示的控制器。这样才能在我想要的控制器里push。
    因为注册通知我写在UIViewController的扩展里,所以如果我通知了5个控制器,那个通知方法会走5遍push5个页面。加个leo字段控制只让其走一次。

    第三种

    推送的时候,App就是打开的状态。这里处理就是加一个弹窗,让用户选择一下就行。我在之前AppDelegate.m代码中已经写了。剩下的和第二种情况一样。

    后记

    其实如果自定义过UIViewController,你所有的ViewController都是继承它。就不用写扩展了。直接在父类中注册通知就行。

    至于为什么不在LeoNavigationController.m中的pushViewController这个方法中直接对push进来的每个ViewController进行通知注册。我试了,不过不知道怎么回事,推送消息走到这里就崩溃了。当时赶项目,就没仔细研究,换一个方法。

    关于《打开App,不管在哪个页面都要跳转对应的页面》大家要是有更好的实现思路欢迎交流~~

    相关文章

      网友评论

        本文标题:消息推送---跳转到指定页面

        本文链接:https://www.haomeiwen.com/subject/ezkhwttx.html