立冬
現在有一個需求,有通知過來,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