哎,軟件進(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)效果:
總結(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)的。