自鉴iOS学习征服iOS

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

2017-02-16  本文已影响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,不管在哪个页面都要跳转对应的页面》大家要是有更好的实现思路欢迎交流~~

上一篇下一篇

猜你喜欢

热点阅读