IOS開(kāi)發(fā)(點(diǎn)擊推送做定向跳轉(zhuǎn))

2688961-43a433f0ff679628.png

哎,軟件進(jìn)入測(cè)試階段了,設(shè)計(jì)這邊來(lái)了一個(gè)新的需求,遠(yuǎn)程推送來(lái)的消息不管是在程序激活狀態(tài)還是后臺(tái)休眠狀態(tài),以及程序沒(méi)有啟動(dòng)的狀態(tài),點(diǎn)擊推送來(lái)的消息都要跳轉(zhuǎn)到消息中心頁(yè)面。

問(wèn)題與難點(diǎn)

但是問(wèn)題又來(lái)了。項(xiàng)目中有些地方是沒(méi)有導(dǎo)航欄的也就是默寫(xiě)試圖控制器是present出來(lái)的并不是push出來(lái)的。然后在程序處于登陸頁(yè)面的時(shí)候由于用戶沒(méi)有登陸所以點(diǎn)擊推送消息是不能進(jìn)行跳轉(zhuǎn)的,所以這時(shí)候就要分類(lèi)討論了。因?yàn)樽罱K都要跳轉(zhuǎn)到消息中心頁(yè)面(MessageCenterViewController消息中西頁(yè)面),但是消息中心頁(yè)面是有導(dǎo)航欄的。(最終邏輯見(jiàn)代碼pushToViewController方法內(nèi)部)。

解決思路

1.如果用戶當(dāng)前正在使用APP也就是程序在激活狀態(tài)下,那么這時(shí)候用戶所在的控制器是含有UINavigationController的控制器,當(dāng)用戶點(diǎn)擊推送消息的時(shí)候,這時(shí)候獲取到當(dāng)前正在顯示的視圖控制器,進(jìn)行跳轉(zhuǎn)push過(guò)去。

2.如果用戶當(dāng)前正在使用APP也就是程序在激活狀態(tài)下,那么這時(shí)候用戶所在的控制器是不含有UINavigationController的控制器,這時(shí)候獲取到當(dāng)前的視圖控制器 給將要跳轉(zhuǎn)的控制器(也就是目標(biāo)控制器你要跳轉(zhuǎn)到的控制器)消息中心(MessageCenterViewController)添加導(dǎo)航欄 然后presentViewController。

3.1.在極光推送的代理方法里面實(shí)現(xiàn)頁(yè)面跳轉(zhuǎn)的邏輯
#pragma mark- JPUSHRegisterDelegate
// iOS 10 Support
- (void)jpushNotificationCenter:(UNUserNotificationCenter *)center willPresentNotification:(UNNotification *)notification withCompletionHandler:(void (^)(NSInteger))completionHandler {

    // Required
    NSDictionary * userInfo = notification.request.content.userInfo;
    if([notification.request.trigger isKindOfClass:[UNPushNotificationTrigger class]]) {
        [JPUSHService handleRemoteNotification:userInfo];
        //判斷程序是否是在激活狀態(tài)下
        if ([UIApplication sharedApplication].applicationState == UIApplicationStateActive) {
       
        }
        
        else{//程序在后臺(tái)以及程序沒(méi)有啟動(dòng)的時(shí)候
            //跳轉(zhuǎn)到指定頁(yè)面
            [self pushToViewController];
        }
    }
    completionHandler(UNNotificationPresentationOptionAlert); // 需要執(zhí)行這個(gè)方法,選擇是否提醒用戶,有Badge、Sound、Alert三種類(lèi)型可以選擇設(shè)置
}
// iOS 10 Support.  極光推送代理方法
- (void)jpushNotificationCenter:(UNUserNotificationCenter *)center didReceiveNotificationResponse:(UNNotificationResponse *)response withCompletionHandler:(void (^)())completionHandler {
    if([response.notification.request.trigger isKindOfClass:[UNPushNotificationTrigger class]]) {
        [JPUSHService handleRemoteNotification:userInfo];
        if ([UIApplication sharedApplication].applicationState == UIApplicationStateActive) {
            //程序運(yùn)行時(shí)收到通知,先彈出消息框
            [self pushToViewController];//程序激活狀態(tài)下點(diǎn)擊跳轉(zhuǎn)邏輯

        }
        
        else{//程序在后臺(tái)以及程序沒(méi)有激活的時(shí)候點(diǎn)擊跳轉(zhuǎn)邏
            //跳轉(zhuǎn)到指定頁(yè)面
            [self pushToViewController];
        }
    }
    completionHandler();  // 系統(tǒng)要求執(zhí)行這個(gè)方法    
}
#pragma mark---- ios 10.0//系統(tǒng)自己的運(yùn)程推送代理方法

- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler {
    
    // Required, iOS 7 Support
    [JPUSHService handleRemoteNotification:userInfo];
    
    completionHandler(UIBackgroundFetchResultNewData);
   
    if (application.applicationState == UIApplicationStateActive || application.applicationState == UIApplicationStateBackground) {
   
    }
    else
    {
        
        //跳轉(zhuǎn)到指定頁(yè)面
        [self pushToViewController];
    }
    
    
}
跳轉(zhuǎn)邏輯實(shí)現(xiàn)方法一
- (void)pushToViewController{//視圖控制器的跳轉(zhuǎn)邏輯
  
    UIViewController *vc = nil;
//判斷根視圖是不是UINavigationController
    if ([self.window.rootViewController isKindOfClass:[UINavigationController class]]) {
       //如果是獲取最上層的控制器也就是當(dāng)前顯示的控制器
        vc = ((UINavigationController *)self.window.rootViewController).viewControllers.lastObject;
    }else{
          //根控制器
        vc = self.window.rootViewController;
    }
    
    //判斷如果是在登錄頁(yè)面,那么不進(jìn)行跳轉(zhuǎn)
    if ([vc isKindOfClass:[LoginViewController class]]) {
        return;
    }
    MessageCenterViewController *messageVC = [MessageCenterViewController new];
    if (vc.presentedViewController) {
        //根控制器不是導(dǎo)航控制器
        messageVC.isPresent = YES;
        //給MessageCenterViewController添加導(dǎo)航欄 因?yàn)辄c(diǎn)擊消息中心頁(yè)面需要跳轉(zhuǎn)到下一頁(yè)面 如果沒(méi)有這個(gè)需求可以不加。
        UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController:messageVC];
       [vc.presentedViewController presentViewController:nav animated:YES completion:nil];
    }else{
        //根控制器是導(dǎo)航控制器
        UINavigationController *nav = (UINavigationController *)vc;
        [nav pushViewController:messageVC animated:YES];
    }
}
跳轉(zhuǎn)邏輯實(shí)現(xiàn)方法二
- (void)pushToViewController{
//視圖控制器的跳轉(zhuǎn)邏輯
    MessageCenterViewController *messageVC = [MessageCenterViewController new];
    UIViewController *topController =[self theTopviewControler];
    NSString *classs =  NSStringFromClass([topController class]);
    
    NSLog(@"%@",classs);
    
    //判斷如果是在登錄頁(yè)面,那么不進(jìn)行跳轉(zhuǎn)
    if ([topController isKindOfClass:[LoginViewController class]]) {
        return;
    }else if ([topController isKindOfClass:[WWTPointSelectionViewController class]]){//如果是從不含導(dǎo)航欄的控制器跳轉(zhuǎn)到消息中西(WWTPointSelectionViewController沒(méi)有導(dǎo)航欄的控制器)
        UINavigationController * Nav = [[UINavigationController alloc]initWithRootViewController:messageVC];
        messageVC.isPresent = YES;
        //這里加導(dǎo)航欄是因?yàn)槲姨D(zhuǎn)的頁(yè)面帶導(dǎo)航欄,如果跳轉(zhuǎn)的頁(yè)面不帶導(dǎo)航,那這句話請(qǐng)省去。
        [topController presentViewController:Nav animated:YES completion:nil];

    }else{
        //根控制器是導(dǎo)航控制器
        UINavigationController *nav = (UINavigationController *)topController;
        [nav pushViewController:messageVC animated:YES];
    
    }
}


//獲取當(dāng)前所展示的控制器
- (UIViewController *)theTopviewControler{
    UIViewController *rootVC = [[UIApplication sharedApplication].delegate window].rootViewController;
    
    UIViewController *parent = rootVC;
    
    while ((parent = rootVC.presentedViewController) != nil ) {
        rootVC = parent;
    }
    
    while ([rootVC isKindOfClass:[UINavigationController class]]) {
        rootVC = [(UINavigationController *)rootVC topViewController];
    }
    
    return rootVC;
}

提示:由于跳轉(zhuǎn)進(jìn)MessageCenterViewController的方式有push和preset兩種類(lèi)型,所以在MessageCenterViewController的返回按鈕需要做下判斷和區(qū)分,(這時(shí)候需要自定義返回按鈕在返回按鈕的方法中做判斷和區(qū)分)如果是push進(jìn)來(lái)的需要popViewControllerAnimated回去,如果是present進(jìn)來(lái)的那么就需要dismissViewControllerAnimated
//返回按鈕執(zhí)行的方法
- (void)doClickPushAction{
    //判斷推送跳轉(zhuǎn)進(jìn)來(lái)的方式,可能是modal過(guò)來(lái)的。也可能是push過(guò)來(lái)的
    if (self.isPresent) {
        [self dismissViewControllerAnimated:YES completion:nil];
        
    }else{
        [self.navigationController popViewControllerAnimated:YES];
    }
}

實(shí)現(xiàn)效果:
程序在激活狀態(tài)下點(diǎn)擊推送消息跳轉(zhuǎn).gif
程序在進(jìn)入后臺(tái)的時(shí)候點(diǎn)擊推送進(jìn)行跳轉(zhuǎn).gif
殺死程序也就是程序未啟動(dòng)的時(shí)候點(diǎn)擊推送跳轉(zhuǎn).gif
總結(jié)

點(diǎn)擊推送消息進(jìn)行指定頁(yè)面的跳轉(zhuǎn),這個(gè)是很常見(jiàn)的需求,一定要考慮到項(xiàng)目中有些界面是有導(dǎo)航欄有些頁(yè)面是沒(méi)有導(dǎo)航欄的,而且在用戶處于登陸頁(yè)面的時(shí)候點(diǎn)擊推送消息是不需要進(jìn)行跳轉(zhuǎn)的。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容