多控制器App概述
- 一个 iOS 的
App
很少由一个控制器组成,除非这个App
极其简单 - 当
App
中有多个控制器的时候,我们就需要对这些控制器进行管理 -
在之前的学习中,有多个 View 时
- 可以用一个大的 View 去管理 1 个或者多个小 View
-
控制器也是如此,用 1 个控制器去管理其他多个控制器
-
举例:用一个控制器
A
去管理 3 个控制器B
、C
、D
- 控制器
A
被称为控制器B
、C
、D
的父控制器
- 控制器
B
、C
、D
被称为控制器A
的子控制器
- 控制器
-
为了便于管理控制器,iOS 提供了 2 个比较特殊的控制器
UINavigationController
导航控制器UITabBarController
TabBar(标签)控制器
- 掌握导航控制器(
UINavigationController
)核心概念 ——栈
- 掌握标签控制器(
UITabBarController
)核心概念 ——平级
- 掌握经典应用程序架构图
- 掌握
Modal
(模态) 展现控制器的时机 - 掌握 Modal 的数据传值方式
- 顺序传值 —— 通过属性
- 逆向传值 —— 通过代理
导航控制器 UINavigationController
UINavigationController 结构示意图
掌握的概念
-
以
栈
的方式管理子视图控制器- 入栈/压栈
addObject:
- 出栈
removeLastObject
- 入栈/压栈
-
UINavigationController
—— 导航控制器view
—— 导航控制器的容器视图
-
UINavigationBar
—— 导航条 UINavigationItem
—— 导航条目
掌握的方法
pushViewController:animated:
压栈,显示新的控制器popViewControllerAnimated:
出栈,返回上一级控制器,如果到栈顶什么也不做
Storyboard 演练
- 在
ViewController
中重写viewDidAppear:
方法,并且实现以下代码
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
NSLog(@"%@", self.navigationItem.title);
NSLog(@"%@", self.navigationController.viewControllers);
}
有关
viewDidAppear:
等相关视图生命周期的方法,在后续介绍视图生命周期
再讲此方法会在每次视图控制器的根视图出现在屏幕上时调用
注意:返回按钮需要在前一个控制器中设置
纯代码演练
- 在
AppDelegate
实现以下代码
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
self.window.backgroundColor = [UIColor whiteColor];
ViewController *vc = [[ViewController alloc] init];
UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController:vc];
self.window.rootViewController = nav;
[self.window makeKeyAndVisible];
return YES;
}
- 在
ViewController
实现以下代码
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
[self setupUI];
}
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
NSLog(@"%@ %zd", self.navigationController.viewControllers, self.navigationController.viewControllers.count);
}
#pragma mark - 监听方法
/// 返回上一个控制器
- (void)backToPrevious {
// 如果已经是栈顶控制器,不会有任何反应
[self.navigationController popViewControllerAnimated:YES];
}
/// 显示下一个控制器
- (void)showNext {
[self.navigationController pushViewController:[[ViewController alloc] init] animated:YES];
}
#pragma mark - 设置界面
- (void)setupUI {
// 0. 设置背景颜色
self.view.backgroundColor = [UIColor whiteColor];
// 1. 设置标题
NSString *title = [NSString stringWithFormat:@"第 %zd 个", self.navigationController.viewControllers.count];
NSString *nextTitle = [NSString stringWithFormat:@"第 %zd 个", self.navigationController.viewControllers.count + 1];
self.title = title;
// 2. 设置右侧按钮
self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:nextTitle style:UIBarButtonItemStylePlain target:self action:@selector(showNext)];
// 3. 添加 pop 按钮
UIButton *btn = [UIButton buttonWithType:UIButtonTypeContactAdd];
btn.center = self.view.center;
[self.view addSubview:btn];
[btn addTarget:self action:@selector(backToPrevious) forControlEvents:UIControlEventTouchUpInside];
}
@end
TabBar 控制器
UITabBarController 结构示意图
概念
-
以
平级
的方式管理子视图控制器- 子控制器一次性创建
- 子控制器不会被销毁
-
UITabBarController
—— 标签控制器view
—— TabBar 控制器的容器视图
-
UITabBar
—— 标签条 -
UITabBarItem
—— 标签条目 -
设置子控制器数组
@property(nullable, nonatomic,copy) NSArray<__kindof UIViewController *> *viewControllers;