极光推送点击消息栏跳转到指定页面、设置标签或别名

上周,完成app新版本的开发。自从进入这版app的开发就没来更新过文章了,接下来会陆陆续续写一下在这过程中遇到的问题及一些总结。今天,就先说说消息推送吧。

推送,大家都不陌生,没有推送功能的app估计是少数。当然,对于推送介绍的文章也非常多也很仔细,但是真正开发过程中,还是会遇到各种问题,接下来会和大家谈谈集成推送的方法及我在开发中遇到的问题,但愿能给你们开发中遇到类似的问题时提供一种思路。

在推送过程我遇到的问题主要有:
1.在点击消息栏进入指定页面后,页面的点击事件不响应
2.点击消息栏进入指定页面后,页面的导航栏问题

其实这两个问题,归根结底是因为跳转时选择的控制器不对。比如当我点击消息栏时,希望跳转到A页面,A中没有导航栏。我开始用的是[self.window.rootViewController presentViewController:A animated:YES completion:nil],这时候跳转到A页面后,A页面中控件的点击事件不起作用了,后面发现,是因为层级图不对。而且用present的话,没有导航栏,所以当你跳转到指定页面A时,如果A页面的点击事件还有跳转到新页面B的功能,那么这个当你通过A push出来的B页面是没有导航栏的,而实际上我们希望的B是有导航栏的。

最后换成了pushViewController的方法。这个方法的关键是,你得找到当前的的VC,比如A页面是通过tabbar的第一个item中的VC的navpush出来的,那么这时候,只要找到tabbar第一个Item对应的nav中VC,然后用这个VC的 nav
push出A页面,问题就可以解决了。

接下来,说说该如何集成极光推送、如何处理收到通知时的页面跳转问题,以及如何设置标签和别名。

一、处理收到通知时页面跳转问题。
1.你需要到极光推送的平台上申请appkey,申请的过程中需要上传开发环境和正式环境的消息推送证书,所以如果你的app还没有消息推送证书,那么你需要到苹果的开发者账号中申请消息推送证书。如果对这个步骤不是很了解的话,可以参照iOS 证书 设置指南

2.申请好极光推送的appkey后,将下载的SDK拖到自己的工程中,添加相应的framework,配置好相关信息。也可参照官方文档
iOS SDK 集成指南

3.在 AppDelegate.m引入

#import "JPUSHService.h"
#ifdef NSFoundationVersionNumber_iOS_9_x_Max
#import <UserNotifications/UserNotifications.h>
#endif 

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions中注册极光推送

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

    self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
    self.window.backgroundColor = [UIColor whiteColor];
    [self initRootViewController];


    if ([[UIDevice currentDevice].systemVersion floatValue] >= 10.0) {
        //iOS10以上
        JPUSHRegisterEntity * entity = [[JPUSHRegisterEntity alloc] init];
        entity.types = UNAuthorizationOptionAlert|UNAuthorizationOptionBadge|UNAuthorizationOptionSound;
        [JPUSHService registerForRemoteNotificationConfig:entity delegate:self];
    }else if ([[UIDevice currentDevice].systemVersion floatValue] >= 8.0) {
        //iOS8以上可以添加自定义categories
        [JPUSHService registerForRemoteNotificationTypes:(UIUserNotificationTypeBadge |
                                                          UIUserNotificationTypeSound |
                                                          UIUserNotificationTypeAlert)
                                              categories:nil];
    }
    else {
        //iOS8以下categories 必须为nil
        [JPUSHService registerForRemoteNotificationTypes:(UIRemoteNotificationTypeBadge |
                                                          UIRemoteNotificationTypeSound |
                                                          UIRemoteNotificationTypeAlert)
                                              categories:nil];
    }
    BOOL isProduction = NO;// NO为开发环境,YES为生产环境

    //Required(2.1.5版本的SDK新增的注册方法,改成可上报IDFA,如果没有使用IDFA直接传nil
    [JPUSHService setupWithOption:launchOptions appKey:@"你的极光推送appkey"
                          channel:nil
                 apsForProduction:isProduction
            advertisingIdentifier:nil];

    //2.1.9版本新增获取registration id block接口。可以获取registrationID
    [JPUSHService registrationIDCompletionHandler:^(int resCode, NSString *registrationID) {
        if(resCode == 0){
            NSLog(@"registrationID获取成功:%@",registrationID);

        }
        else{
            NSLog(@"registrationID获取失败,code:%d",resCode);
        }
    }];


    return YES;
}

注册deviceToken

#pragma mark--注册devicetoken
- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {

    [JPUSHService registerDeviceToken:deviceToken];
}

收到通知时的处理 ,这里需要注意一下,iOS10收到通知时的方法和iOS10以前的不一样

- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler {
    [JPUSHService handleRemoteNotification:userInfo];

    completionHandler(UIBackgroundFetchResultNewData);

    if (_application.applicationState == UIApplicationStateActive) {
        //程序运行时收到通知,先弹出消息框

        [self getPushMessageAtStateActive:userInfo];

    }

    else{
        //程序已经关闭或者在后台运行
        [self pushToViewControllerWhenClickPushMessageWith:userInfo];

    }

    [application setApplicationIconBadgeNumber:0];

    [JPUSHService handleRemoteNotification:userInfo];

    completionHandler(UIBackgroundFetchResultNewData);
}

#ifdef NSFoundationVersionNumber_iOS_9_x_Max
#pragma mark- JPUSHRegisterDelegate
-(void)jpushNotificationCenter:(UNUserNotificationCenter *)center
       willPresentNotification:(UNNotification *)notification withCompletionHandler:(void (^)(NSInteger))completionHandler {

    NSDictionary * userInfo = notification.request.content.userInfo;
    UNNotificationRequest *request = notification.request; // 收到推送的请求
    UNNotificationContent *content = request.content; // 收到推送的消息内容


    if([notification.request.trigger isKindOfClass:[UNPushNotificationTrigger class]]) {
        [JPUSHService handleRemoteNotification:userInfo];


        if (_application.applicationState == UIApplicationStateActive) {
            //程序运行时收到通知,先弹出消息框

            [self getPushMessageAtStateActive:userInfo];

        }

        else{

            [self pushToViewControllerWhenClickPushMessageWith:userInfo];
        }

    }
    // 需要执行这个方法,选择是否提醒用户,有Badge、Sound、Alert三种类型可以设置
    completionHandler(UNNotificationPresentationOptionBadge|UNNotificationPresentationOptionSound|UNNotificationPresentationOptionAlert);
}
//
-(void)jpushNotificationCenter:(UNUserNotificationCenter *)center
didReceiveNotificationResponse:(UNNotificationResponse *)response withCompletionHandler:(void (^)())completionHandler {
    NSDictionary * userInfo = response.notification.request.content.userInfo;
    [[NSUserDefaults standardUserDefaults] setObject:@"Inactive" forKey:@"applicationState"];

    if([response.notification.request.trigger isKindOfClass:[UNPushNotificationTrigger class]]) {
        [JPUSHService handleRemoteNotification:userInfo];


        if (_application.applicationState == UIApplicationStateActive) {
            //程序运行时收到通知,先弹出消息框
            [self getPushMessageAtStateActive:userInfo];

            [[NSNotificationCenter defaultCenter] postNotificationName:@"ApplicationState" object:@"0"];

        }

        else{

            [self pushToViewControllerWhenClickPushMessageWith:userInfo];
        }

    }
    completionHandler();  // 系统要求执行这个方法
}
#endif

如果在程序运行时收到通知,这时消息栏不会显示通知,所以如果想让用户收到通知的话,应该是给用户一个弹框提醒,告诉用户有消息通知,当用户点击提示框中的确认查看按钮时,跳转到指定的页面

#pragma mark -- 程序运行时收到通知
-(void)getPushMessageAtStateActive:(NSDictionary *)pushMessageDic{

        UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@""
                                                                                 message:[[pushMessageDic objectForKey:@"aps"]objectForKey:@"alert"]
                                                                          preferredStyle:UIAlertControllerStyleAlert];

        UIAlertAction *confirmAction = [UIAlertAction actionWithTitle:@"查看"
                                                              style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {

                                                                  [self pushToViewControllerWhenClickPushMessageWith:pushMessageDic];
                                                              }];

        UIAlertAction *cancelAction = [UIAlertAction actionWithTitle:@"取消"
                                                               style:UIAlertActionStyleCancel handler:^(UIAlertAction * _Nonnull action) {

                                                               }];

        [alertController addAction:confirmAction];
        [alertController addAction:cancelAction];
        [self.window.rootViewController presentViewController:alertController animated:YES completion:nil];


}

跳转到指定页面的方法。跳转到指定页面的话,可能会需要某些参数,这时可以根后台商定,根据参数跳转到相应的页面,同时也让后台把你需要的参数返回来。比如我和后台商定根据“pageType”这个参数确定跳转的页面。如果是跳转到次级页面,这里重要的是要找到正确的viewcontroller,用controller的nav进行push新页面。比如我的DetailViewController是用tabar的第一个item中的FirstViewController的nav进行push出来的,那么,当我点击通知消息想到跳转到DetailViewController,只要找到FirstViewController就可以了。

-(void)pushToViewControllerWhenClickPushMessageWith:(NSDictionary*)msgDic{


    NSUserDefaults*pushJudge = [NSUserDefaults standardUserDefaults];

            if ([[msgDic objectForKey:@"pageType"] integerValue]==0){

//      跳转到第一个tabbarItem,这时直接设置 UITabBarController的selectedIndex属性就可以

             self.tabController.selectedIndex = 0;

            }else if ([[msgDic objectForKey:@"pageType"] integerValue]==1){

                //跳转到第二个tabbarItem

                self.tabController.selectedIndex = 1;


            }else if ([[msgDic objectForKey:@"pageType"] integerValue]==2){
                //跳转到第三个tabbarItem


                self.tabController.selectedIndex = 2;

            }else if ([[msgDic objectForKey:@"pageType"] integerValue]==3){
                //详情,这是从跳转到第一个tabbarItem跳转过去的,所以我们可以先让tabController.selectedIndex =0;然后找到VC的nav。

                self.tabController.selectedIndex =0;
                DetailViewController * VC = [[DetailViewController alloc]init];
                [VC setHidesBottomBarWhenPushed:YES];
            //因为我用了三方全屏侧滑手势,所以要找的是第一个tabbarController中的viewController的JTNavigationController ,接着再找JTNavigationController 里面的jt_viewControllers.lastObject,这样就可以找到FirstViewController了,然后跳转的时候就和正常的跳转一样了
                JTNavigationController *nav=(JTNavigationController *)self.tabController.viewControllers[0];
                UIViewController *vc=(UIViewController*)nav.jt_viewControllers.lastObject;

                [vc.navigationController pushViewController:VC animated:NO];

            }else {

            }

}

二、如何设置标签或者别名
消息推送,有时候只想推送给指定的人或者指定的版本,那么这时候我们就需要对设备设置标签或者别名了,这样推送的时候可以根据标签或者别名推送给指定的用户

- (void)viewDidLoad {
    [super viewDidLoad];
    self.view.backgroundColor = [UIColor whiteColor];

    //标签
    __autoreleasing NSMutableSet *tags = [NSMutableSet set];
    //设置了IOS_ALL的标签,当推送时选了IOS_ALL这标签,那么只要装了这个app并且允许消息推送的用户就都能收到通知
    [self setTags:&tags addTag:@"IOS_ALL"];

    NSString  *version = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleShortVersionString"];
    //根据版本号设置了IOSXX的标签,当推送时选了IOS2.1这标签,那么只要装了这个app并且允许消息推送的2.1版本的用户就都能收到通知

    [self setTags:&tags addTag:[NSString stringWithFormat:@"IOS%@",version]];

    if (_isLogin==YES) {
        //根据版本号设置了LoginUesr的标签,当推送时选了LoginUesr这标签,那么只要装了这个app并且允许消息推送的所有登录用户就都能收到通知
        [self setTags:&tags addTag:@"LoginUesr"];
    }else{

    }

    //别名,根据用户的UID去设置别名,那么可以指定的推送给某些用户
    __autoreleasing NSString *alias ;

    if (_userUID!= nil) {
        alias =[NSString stringWithFormat:@"%@",_userUID];


    }
    [self analyseInput:&alias tags:&tags];

    [JPUSHService setTags:tags alias:alias callbackSelector:@selector(tagsAliasCallback:tags:alias:) object:self];
}
- (void)tagsAliasCallback:(int)iResCode
                     tags:(NSSet *)tags
                    alias:(NSString *)alias {
    NSString *callbackString =
    [NSString stringWithFormat:@"%d, \ntags: %@, \nalias: %@\n", iResCode,
     [self logSet:tags], alias];

    NSLog(@"TagsAlias回调:%@", callbackString);
}
- (NSString *)logSet:(NSSet *)dic {
    if (![dic count]) {
        return nil;
    }
    NSString *tempStr1 =
    [[dic description] stringByReplacingOccurrencesOfString:@"\\u"
                                                 withString:@"\\U"];
    NSString *tempStr2 =
    [tempStr1 stringByReplacingOccurrencesOfString:@"\"" withString:@"\\\""];
    NSString *tempStr3 =
    [[@"\"" stringByAppendingString:tempStr2] stringByAppendingString:@"\""];
    NSData *tempData = [tempStr3 dataUsingEncoding:NSUTF8StringEncoding];
    NSString *str =
    [NSPropertyListSerialization propertyListFromData:tempData
                                     mutabilityOption:NSPropertyListImmutable
                                               format:NULL
                                     errorDescription:NULL];
    return str;
}
#pragma mark--设置推送的标签及别名
- (void)setTags:(NSMutableSet **)tags addTag:(NSString *)tag {

    [*tags addObject:tag];
}
- (void)analyseInput:(NSString **)alias tags:(NSSet **)tags {
    // alias analyse
    if (![*alias length]) {
        // ignore alias
        *alias = nil;
    }
    // tags analyse
    if (![*tags count]) {
        *tags = nil;
    } else {
        __block int emptyStringCount = 0;
        [*tags enumerateObjectsUsingBlock:^(NSString *tag, BOOL *stop) {
            if ([tag isEqualToString:@""]) {
                emptyStringCount++;
            } else {
                emptyStringCount = 0;
                *stop = YES;
            }
        }];
        if (emptyStringCount == [*tags count]) {
            *tags = nil;
        }
    }
}

当用户退出登录的时候可以重置别名,不然设备还是会收到通知

[JPUSHService setAlias:@"" callbackSelector:@selector(tagsAliasCallback:tags:alias:) object:self];

以上就是对于极光推送的简单介绍,如有问题欢迎指出或留言。

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值