ios 收到遠程通知,點擊跳轉到對應的消息界面

立冬

現在有一個需求,有通知過來,app處于前臺時,彈出一個alert,點擊確定跳轉到對應的界面,在這里我設了一個定時器,模擬接收到通知彈出alert,通知的集成代碼這邊就不多做介紹了,想了解集成我的上篇文章中有簡單的介紹,下面開始分兩種情況

1. self.window.rootViewController是導航控制器

appdelegate.m

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    // MainTabbarVC為tabbarController
    MainTabbarVC *main = [[MainTabbarVC alloc] init];
    UINavigationController *nvc = [[UINavigationController alloc] initWithRootViewController:main];
    self.window.rootViewController = nvc;
    [self.window makeKeyAndVisible];
// 設定一個彈出alert的定時器
    time = [NSTimer scheduledTimerWithTimeInterval:2 target:self selector:@selector(showAlert) userInfo:nil repeats:NO];
    return YES;
}

- (void)showAlert
{
    UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"是否去消息界面" message:@"請選擇" preferredStyle:UIAlertControllerStyleAlert];    
    UIAlertAction *alertAction = [UIAlertAction actionWithTitle:@"跳轉" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
        //  點擊確定,處理頁面跳轉
        ViewController *viewC = [[ViewController alloc] init];
        NSLog(@"點擊了確定,push");
    }];
    
    UIAlertAction *cancelAction = [UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleCancel handler:nil];  
    [alertController addAction:alertAction];
    [alertController addAction:cancelAction];    
//    MainTabbarVC *main = [[MainTabbarVC alloc] init];
//    [main presentViewController:alertController animated:YES completion:nil];
//    HomeViewController *home = [[HomeViewController alloc] init];
//    [home presentViewController:alertController animated:YES completion:nil];  // 主頁
// 以上兩種方法無法彈出alert

// 用rootViewController彈出laert
[self.window.rootViewController presentViewController:alertController animated:YES completion:nil];

    [time invalidate]; // 取消定時器
}
彈出alert

接下來著重說一下跳轉的方法

1.用self.window.rootViewController去push

ViewController *viewC = [[ViewController alloc] init];
[(UINavigationController *)self.window.rootViewController pushViewController:viewC animated:YES]; // 這里需要強制轉化一下,這個方法不推薦,當項目中業務邏輯比較復雜的時候,此方法可能會導致很多bug,待會會介紹另外一種寫法

self.window.rootViewController實際上是MainTabbarVC

打斷點,用po命令查看

下面看一下MainTabbarVC里面的代碼

#import "MainTabbarVC.h"
#import "HomeViewController.h"
#import "SettingViewController.h"

@interface MainTabbarVC ()

@end

@implementation MainTabbarVC

// 程序進入隱藏appdelegate里面創建的navigation ,這一步很關鍵,不然進入主頁面,看到的navigation將是在appdelegate里面創建的,不利于管理
- (void)viewWillAppear:(BOOL)animated{    
    [super viewWillAppear:animated];
    self.navigationController.navigationBarHidden = YES;
}
- (void)viewDidLoad {
    [super viewDidLoad];    
    [self creatControllers];
}

- (void)creatControllers
{
    HomeViewController *home = [[HomeViewController alloc] init];
    UINavigationController *homeNAV = [[UINavigationController alloc] initWithRootViewController:home];
    home.title = @"主頁";
    
    SettingViewController *setting = [[SettingViewController alloc] init];
    UINavigationController *settingNAV = [[UINavigationController alloc] initWithRootViewController:setting];
    setting.title = @"設置";
    
    self.viewControllers = @[homeNAV,settingNAV];
    
}

跳轉后的頁面效果


跳轉后的viewController

1.2 剛才說了上面的push方法不推薦,下面推薦一個比較合理的方法在Appdelegate.m中

#import "AppDelegate.h"
#import "MainTabbarVC.h"
#import "ViewController.h"
@interface AppDelegate ()
{
     NSTimer *time;
}
@end
static AppDelegate *__delegate = nil;
@implementation AppDelegate
AppDelegate *myDelegate(void){
    return __delegate;
}

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    
    MainTabbarVC *main = [[MainTabbarVC alloc] init];
    self.window.rootViewController = main;
    __delegate = self;
    _masterTabbarController = main;    
    [self.window makeKeyAndVisible];  
    time = [NSTimer scheduledTimerWithTimeInterval:2 target:self selector:@selector(showAlert) userInfo:nil repeats:NO];
    return YES;
}

// alert中push
 UIAlertAction *alertAction = [UIAlertAction actionWithTitle:@"跳轉" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
        // 跳轉頁面 跳轉到消息列表頁面
        ViewController *viewC = [[ViewController alloc] init];
        [AppDelegate mastePushViewController:viewC];
    }];


// push方法
+ (void)mastePushViewController:(UIViewController *)controller
{
    UINavigationController *nvc = myDelegate().masterTabbarController.selectedViewController;
    [nvc pushViewController:controller animated:YES];
}

push之后的效果如下


直接拿到tabbarController的navigation

viewController.m

#import "ViewController.h"

@interface ViewController ()

@end

@implementation ViewController
// 顯示隱藏的導航欄
- (void)viewWillAppear:(BOOL)animated{
    [super viewWillAppear:animated];
    self.navigationController.navigationBarHidden = NO;   
}

- (void)viewDidLoad {
    [super viewDidLoad];
    self.view.backgroundColor = [UIColor cyanColor];
    self.title = @"viewController";
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
}
@end

2. self.window.rootViewController不是導航控制器

appdelegate.m

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {   
    MainTabbarVC *main = [[MainTabbarVC alloc] init];
    self.window.rootViewController = main;
    [self.window makeKeyAndVisible];
    time = [NSTimer scheduledTimerWithTimeInterval:2 target:self selector:@selector(showAlert) userInfo:nil repeats:NO];
    return YES;
}

這種情況下,利用以上跳轉方法,程序會crash,下面是奔潰信息


奔潰信息

主要是說MainTabbarVC沒有push方法,我們知道沒有導航控制器是不可能用push,所以這里我們建一個navigationController,然后在跳轉的時候隱藏創建的這個

AppDelegate.h

AppDelegate.h加一個navigation

AppDelegate.m


#import "AppDelegate.h"
#import "MainTabbarVC.h"
#import "ViewController.h"

@interface AppDelegate ()
{
    NSTimer *time;
}

@end

static AppDelegate *__delegate = nil;

@implementation AppDelegate

AppDelegate *myDelegate(void){
    return __delegate;
}

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    
    MainTabbarVC *main = [[MainTabbarVC alloc] init];
    self.myNavigationController = [[UINavigationController alloc] initWithRootViewController:main];
    __delegate = self;
// push的時候隱藏navigationBarHidden
    self.myNavigationController.navigationBarHidden = YES;
    self.window.rootViewController = main;
    
    [self.window makeKeyAndVisible];
    
    time = [NSTimer scheduledTimerWithTimeInterval:2 target:self selector:@selector(showAlert) userInfo:nil repeats:NO];
    return YES;
}

+ (void)myPushViewController:(UIViewController *)controller
{
    UINavigationController *nvc = myDelegate().myNavigationController;
    [nvc pushViewController:controller animated:YES];
}

彈出的alert

- (void)showAlert
{
    UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"是否去消息界面" message:@"請選擇" preferredStyle:UIAlertControllerStyleAlert];    
    UIAlertAction *alertAction = [UIAlertAction actionWithTitle:@"跳轉" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
        // 跳轉頁面 跳轉到消息列表頁面
        ViewController *viewC = [[ViewController alloc] init];
       [AppDelegate myPushViewController:viewC];
        NSLog(@"點擊了確定,準備push");
    }];    
    UIAlertAction *cancelAction = [UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleCancel handler:nil];    
    [alertController addAction:alertAction];
    [alertController addAction:cancelAction];    
    [self.myNavigationController presentViewController:alertAction animated:YES completion:nil];
//    [self.window.rootViewController presentViewController:alertController animated:YES completion:nil];  // 因為self.window.rootViewController = self.myNavigationController,所以這兩個方法是一樣的    
    [time invalidate];
}

核心代碼:


創建navigation

彈框的代碼

彈出alert

這里遇到接收推送后跳轉消息界面,可以重新封裝一個類,將下面這個方法放到封裝的類中,可以全局調用此方法處理消息跳轉

+ (void)myPushViewController:(UIViewController *)controller
{
    UINavigationController *nvc = myDelegate().myNavigationController;
    [nvc pushViewController:controller animated:YES];
}
// 當然,你也可以不用那么繁瑣,直接用[self .myNavigationController pushViewController:controller animated:YES];  // push到想要跳轉的控制器即可

3、不管是不是導航控制器,我么都可以使用通知,然后通知首頁進行跳轉,在appdelegate里面,發送通知,代碼如下

// 這里是接收到遠程推送,點擊通知之后,在需要做特定跳轉的方法里面的
HomeTBVC *home = [[HomeTBVC alloc] init];  // 初始化一下首頁試圖控制器
            //是推送打開
            NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
            [center postNotificationName:@"appdelegatePushMessage" object:nil userInfo:userInfo];  // userInfo為通知內容

4、在首頁試圖控制器下添加代碼

// 添加監聽
[center addObserver:self selector:@selector(pushToWebView:) name:@"appdelegatePushMessage" object:nil];

// 跳轉到相應的頁面,這里的notificaiton.userInfo為遠程通知內容
- (void)pushToWebView:(NSNotification *)notification{
    WebViewVC *webVC = [WebViewVC new];
    webVC.messageDic = notification.userInfo;
    webVC.strUrl = notification.userInfo[@"webUrl"];
    [self.navigationController pushViewController:webVC animated:YES];
}

至此:

可以看出appdelegate里面沒有導航控制器(navigation)的時候,可以選擇創建一個臨時的navigation,在進入tabbarController的時候隱藏;或者直接拿到tabbarcontroller里面創建的navigation,這種方法在跳轉之后底部tabbar不會消失,如果不想要tabbar,可以再push的頁面中隱藏tabbar

現實有很多拘束,但是代碼的世界里,你可以盡情遨游,加油everyone

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容