JPush推送之當(dāng)進(jìn)程被終止的處理

當(dāng)系統(tǒng)通知欄接收到JPush遠(yuǎn)程推送消息,并實(shí)現(xiàn)點(diǎn)擊消息跳轉(zhuǎn)指定頁面,處理推送消息的回調(diào)函數(shù)如下:

- (void)jpushNotificationCenter:(UNUserNotificationCenter *)center didReceiveNotificationResponse:(UNNotificationResponse *)response withCompletionHandler:(void (^)())completionHandler {
    
    NSDictionary * userInfo = response.notification.request.content.userInfo;
    UNNotificationRequest *request = response.notification.request; // 收到推送的請(qǐng)求
    UNNotificationContent *content = request.content; // 收到推送的消息內(nèi)容
    NSNumber *badge = content.badge;  // 推送消息的角標(biāo)
    NSString *body = content.body;    // 推送消息體
    UNNotificationSound *sound = content.sound;  // 推送消息的聲音
    NSString *subtitle = content.subtitle;  // 推送消息的副標(biāo)題
    NSString *title = content.title;  // 推送消息的標(biāo)題
    
    if([response.notification.request.trigger isKindOfClass:[UNPushNotificationTrigger class]]) {
        if (userInfo) {
            [self push:userInfo];
        }else{
            return;
        }
        [JPUSHService handleRemoteNotification:userInfo];
    }
    else {
    }
    completionHandler();  // 系統(tǒng)要求執(zhí)行這個(gè)方法
}

一顽照、我們需要分析有哪些跳轉(zhuǎn)的情景:

1、程序在前臺(tái)運(yùn)行時(shí)接收到消息
2闽寡、程序在后臺(tái)運(yùn)行時(shí)接收到消息
3代兵、程序處于終止(殺死)狀態(tài)下接收到消息

那么本文重點(diǎn)來探討下當(dāng)程序處于終止?fàn)顟B(tài)下時(shí)接收到消息如何處理?

不設(shè)懸念直入主題吧爷狈,仿照QQ植影、微信等其他APP的推送機(jī)制可以了解到,當(dāng)程序被終止?fàn)顟B(tài)下涎永,點(diǎn)擊通知欄的消息只打開app并不能跳轉(zhuǎn)特定頁面思币,原因是appDelegate的main函數(shù)不執(zhí)行,那么Push的載體導(dǎo)航器也不存在羡微。系統(tǒng)只能根據(jù)通知欄所點(diǎn)擊消息對(duì)應(yīng)遠(yuǎn)程推送注冊(cè)碼來選擇啟動(dòng)哪一個(gè)APP.

所以消息處理的邏輯即:

1谷饿、程序未被終止?fàn)顟B(tài)下,編寫正常跳轉(zhuǎn)特定頁面的代碼
2妈倔、程序被終止?fàn)顟B(tài)下博投,屏蔽Push跳轉(zhuǎn)代碼,只啟動(dòng)app即可

二盯蝴、問題來了毅哗,進(jìn)程被終止回調(diào)機(jī)制是什么呢听怕?

1、程序進(jìn)程被終止會(huì)調(diào)用此函數(shù)

// 程序進(jìn)程被終止時(shí)調(diào)用
- (void)applicationWillTerminate:(UIApplication *)application{
    [[NSUserDefaults standardUserDefaults] setObject:applicationWillTerminate forKey:applicationWillTerminate];
    [[NSUserDefaults standardUserDefaults] synchronize];
}

需要注意:此回調(diào)函數(shù)不能主動(dòng)被調(diào)起虑绵,還需要在程序進(jìn)入后臺(tái)的回調(diào)函數(shù)中開啟UIBackgroundTaskIdentifier任務(wù)尿瞭,即如下操作

2、聲明全局變量

UIBackgroundTaskIdentifier _bgTask;

3翅睛、開啟后臺(tái)任務(wù)

- (void)applicationDidEnterBackground:(UIApplication *)application {    
    _bgTask = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{
        // Synchronize the cleanup call on the main thread in case
        // the task actually finishes at around the same time.
        dispatch_async(dispatch_get_main_queue(), ^{
            if (_bgTask != UIBackgroundTaskInvalid)
            {
                [[UIApplication sharedApplication] endBackgroundTask:_bgTask];
                _bgTask = UIBackgroundTaskInvalid;
            }
        });
    }];
}

亦可在程序進(jìn)入后臺(tái)執(zhí)行一些保存声搁、清理操作

[[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^(){
//程序在10分鐘內(nèi)未被系統(tǒng)關(guān)閉或者強(qiáng)制關(guān)閉,則程序會(huì)調(diào)用此代碼塊宏所,可以在這里做一些保存或者清理工作
NSLog(@"程序關(guān)閉");
}];
三酥艳、如何判斷當(dāng)前的程序是否已經(jīng)被終止呢?

顯然普通的BOOL或者屬性記錄是行不通的爬骤,appDelegate的代碼就不執(zhí)行充石,那么找到的解決方案是:輕量級(jí)存儲(chǔ)。

1霞玄、定義常量

// 定義當(dāng)前程序被終止常量
static NSString *const applicationWillTerminate = @"applicationWillTerminate";

2骤铃、記錄進(jìn)程被強(qiáng)制終止

// 程序進(jìn)程被終止時(shí)調(diào)用
- (void)applicationWillTerminate:(UIApplication *)application{
    [[NSUserDefaults standardUserDefaults] setObject:applicationWillTerminate forKey:applicationWillTerminate];
    [[NSUserDefaults standardUserDefaults] synchronize];
}

3、當(dāng)已啟動(dòng)進(jìn)程時(shí)remove掉存儲(chǔ)對(duì)象坷剧。

    [[NSUserDefaults standardUserDefaults] removeObjectForKey:applicationWillTerminate];
    [[NSUserDefaults standardUserDefaults] synchronize];

四惰爬、runtime處理推送消息跳轉(zhuǎn)特定頁面源碼
- (void)push:(NSDictionary *)userInfo
{
    NSDictionary *params;
    if ([[NSString stringWithFormat:@"%@",userInfo[@"aps"][@"badge"]] isEqualToString:@"1"]) {
        //邀請(qǐng)面試
        params = @{
                   @"class": @"InterviewTimeViewController",
                   @"property": @{
                           @"ID": @"123",
                           @"channelType": @"12"
                           }
                   };
    }else if ([[NSString stringWithFormat:@"%@",userInfo[@"extrasKey"]] isEqualToString:@"0"]){
        //查看簡歷狀態(tài)
        params = @{
                   @"class": @"ResumeStateViewController",
                   @"property": @{
                           @"ID": @"234",
                           @"channelType": @"13"
                           }
                   };
    }

    // 類名
    NSString *classStr =[NSString stringWithFormat:@"%@", params[@"class"]];
    const char *className = [classStr cStringUsingEncoding:NSASCIIStringEncoding];
    
    // 從一個(gè)字串返回一個(gè)類
    Class newClass = objc_getClass(className);
    if (!newClass)
    {
        // 創(chuàng)建一個(gè)類
        Class superClass = [NSObject class];
        newClass = objc_allocateClassPair(superClass, className, 0);
        // 注冊(cè)你創(chuàng)建的這個(gè)類
        objc_registerClassPair(newClass);
    }
    // 創(chuàng)建對(duì)象
    id instance = [[newClass alloc] init];
    
    // 對(duì)該對(duì)象賦值屬性
    NSDictionary * propertys = params[@"property"];
    [propertys enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) {
        // 檢測(cè)這個(gè)對(duì)象是否存在該屬性
        if ([self checkIsExistPropertyWithInstance:instance verifyPropertyName:key]) {
            // 利用kvc賦值
            [instance setValue:obj forKey:key];
        }
    }];
    
    NSString *terminate = [[NSUserDefaults standardUserDefaults] objectForKey:applicationWillTerminate];
    if (![terminate isEqualToString:applicationWillTerminate]) {
        // 獲取導(dǎo)航控制器
        UITabBarController *tabVC = (UITabBarController *)self.window.rootViewController;
        UINavigationController *pushClassStance = (UINavigationController *)tabVC.viewControllers[tabVC.selectedIndex];
        // 跳轉(zhuǎn)到對(duì)應(yīng)的控制器
        [pushClassStance pushViewController:instance animated:YES];
    }
}



- (BOOL)checkIsExistPropertyWithInstance:(id)instance verifyPropertyName:(NSString *)verifyPropertyName
{
    unsigned int outCount, i;
    
    // 獲取對(duì)象里的屬性列表
    objc_property_t * properties = class_copyPropertyList([instance
                                                           class], &outCount);
    for (i = 0; i < outCount; i++) {
        objc_property_t property =properties[i];
        //  屬性名轉(zhuǎn)成字符串
        NSString *propertyName = [[NSString alloc] initWithCString:property_getName(property) encoding:NSUTF8StringEncoding];
        // 判斷該屬性是否存在
        if ([propertyName isEqualToString:verifyPropertyName]) {
            free(properties);
            return YES;
        }
    }
    free(properties);
    
    return NO;
}

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市惫企,隨后出現(xiàn)的幾起案子撕瞧,更是在濱河造成了極大的恐慌,老刑警劉巖狞尔,帶你破解...
    沈念sama閱讀 222,252評(píng)論 6 516
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件丛版,死亡現(xiàn)場離奇詭異,居然都是意外死亡偏序,警方通過查閱死者的電腦和手機(jī)页畦,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,886評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來研儒,“玉大人豫缨,你說我怎么就攤上這事《硕洌” “怎么了好芭?”我有些...
    開封第一講書人閱讀 168,814評(píng)論 0 361
  • 文/不壞的土叔 我叫張陵,是天一觀的道長冲呢。 經(jīng)常有香客問我栓撞,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,869評(píng)論 1 299
  • 正文 為了忘掉前任瓤湘,我火速辦了婚禮,結(jié)果婚禮上恩尾,老公的妹妹穿的比我還像新娘弛说。我一直安慰自己,他們只是感情好翰意,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,888評(píng)論 6 398
  • 文/花漫 我一把揭開白布木人。 她就那樣靜靜地躺著,像睡著了一般冀偶。 火紅的嫁衣襯著肌膚如雪醒第。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,475評(píng)論 1 312
  • 那天进鸠,我揣著相機(jī)與錄音稠曼,去河邊找鬼。 笑死客年,一個(gè)胖子當(dāng)著我的面吹牛霞幅,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播量瓜,決...
    沈念sama閱讀 41,010評(píng)論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼司恳,長吁一口氣:“原來是場噩夢(mèng)啊……” “哼!你這毒婦竟也來了绍傲?” 一聲冷哼從身側(cè)響起扔傅,我...
    開封第一講書人閱讀 39,924評(píng)論 0 277
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎烫饼,沒想到半個(gè)月后猎塞,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,469評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡枫弟,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,552評(píng)論 3 342
  • 正文 我和宋清朗相戀三年邢享,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片淡诗。...
    茶點(diǎn)故事閱讀 40,680評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡骇塘,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出韩容,到底是詐尸還是另有隱情款违,我是刑警寧澤,帶...
    沈念sama閱讀 36,362評(píng)論 5 351
  • 正文 年R本政府宣布群凶,位于F島的核電站插爹,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜赠尾,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,037評(píng)論 3 335
  • 文/蒙蒙 一力穗、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧气嫁,春花似錦当窗、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,519評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至梯影,卻和暖如春巫员,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背甲棍。 一陣腳步聲響...
    開封第一講書人閱讀 33,621評(píng)論 1 274
  • 我被黑心中介騙來泰國打工简识, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人救军。 一個(gè)月前我還...
    沈念sama閱讀 49,099評(píng)論 3 378
  • 正文 我出身青樓财异,卻偏偏與公主長得像,于是被迫代替她去往敵國和親唱遭。 傳聞我的和親對(duì)象是個(gè)殘疾皇子戳寸,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,691評(píng)論 2 361

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