- iOS中控制器的生命周期
一般我们在创建控制器的时候,有三种方法。
1. 直接通过代码创建
2. 通过storyboard创建
3. 通过Xib,在创建控制器的时候传入一个Xib文件作为这个控制器的view。
- 直接通过代码创建
通过代码创建这种凡是,我们打印调用顺序可以发现
对应的代码调用顺序就是 loadView -> viewDidLoad -> viewWillAppear -> viewWillLayoutSubviews -> viewDidLayoutSubviews -> viewDidAppear
// 1. - (void)loadView; // This is where subclasses should create their custom view hierarchy if they aren‘t using a nib. Should never be called directly. // 2. - (void)viewDidLoad; // Called after the view has been loaded. For view controllers created in code, this is after -loadView. For view controllers unarchived from a nib, this is after the view is set. // 3. - (void)viewWillAppear:(BOOL)animated; // Called when the view is about to made visible. Default does nothing // 4. - (void)viewWillLayoutSubviews NS_AVAILABLE_IOS(5_0); // Called just after the view controller‘s view‘s layoutSubviews method is invoked. Subclasses can implement as necessary. The default is a nop. // 5. - (void)viewDidLayoutSubviews NS_AVAILABLE_IOS(5_0);
控制器创建之后,弹出另一个控制器(当前控制器消失),执行的代码顺序 viewWillDisappear -> viewWillLayoutSubviews -> viewDidLayoutSubviews -> viewDidDisappear
// 1. - (void)viewWillDisappear:(BOOL)animated; // Called when the view is dismissed, covered or otherwise hidden. Default does nothing // 2. - (void)viewWillLayoutSubviews NS_AVAILABLE_IOS(5_0); // Called just after the view controller‘s view‘s layoutSubviews method is invoked. Subclasses can implement as necessary. The default is a nop. // 3. - (void)viewDidLayoutSubviews NS_AVAILABLE_IOS(5_0); // 4. - (void)viewDidDisappear:(BOOL)animated; // Called after the view was dismissed, covered or otherwise hidden. Default does nothing
- 通过storyboard创建控制器
UIStoryboard *storyBoard = [UIStoryboard storyboardWithName:NSStringFromClass([CViewController class]) bundle:nil]; CViewController *touch = [storyBoard instantiateViewControllerWithIdentifier:NSStringFromClass([CViewController class])]; [self presentViewController:touch animated:YES completion:nil];
为了方便,同时减少手误,这里重用ID我们使用类名
通过打印来观察
可以看到代码的调用顺序就是 awakeFromNib -> loadView -> viewWillAppear -> viewWillLayoutSubviews -> viewDidLayoutSubviews -> viewDidAppear
// 1. - (void)awakeFromNib NS_REQUIRES_SUPER; // 2. - (void)loadView; // This is where subclasses should create their custom view hierarchy if they aren‘t using a nib. Should never be called directly. // 3. - (void)viewDidLoad; // Called after the view has been loaded. For view controllers created in code, this is after -loadView. For view controllers unarchived from a nib, this is after the view is set. // 4. - (void)viewWillAppear:(BOOL)animated; // Called when the view is about to made visible. Default does nothing // 5. - (void)viewWillLayoutSubviews NS_AVAILABLE_IOS(5_0); // Called just after the view controller‘s view‘s layoutSubviews method is invoked. Subclasses can implement as necessary. The default is a nop. - (void)viewDidLayoutSubviews NS_AVAILABLE_IOS(5_0); // 6. - (void)viewDidAppear:(BOOL)animated; // Called when the view has been fully transitioned onto the screen. Default does nothing
这里需要注意的是,我们是控制器通过storyboard来加载,那么是根据storyboard的描述创建view。
- 通过XIB来创建加载控制器
首先创建一个XIB,快捷键 command + N 来创建。
创建后XIB之后我们还需要设置文件
- 这里设置为我们创建的控制器
所有需要的已经设置好,这时候我们可以来码代码了。
DViewController *touch = [[DViewController alloc] initWithNibName:NSStringFromClass([DViewController class]) bundle:nil]; [self presentViewController:touch animated:YES completion:nil];
下面我们来观察控制器的生命周期
代码层面上就是
// 1. - (void)loadView; // This is where subclasses should create their custom view hierarchy if they aren‘t using a nib. Should never be called directly. // 2. - (void)viewDidLoad; // Called after the view has been loaded. For view controllers created in code, this is after -loadView. For view controllers unarchived from a nib, this is after the view is set. // 3. - (void)viewWillAppear:(BOOL)animated; // Called when the view is about to made visible. Default does nothing // 4.可能会多次调用 - (void)viewWillLayoutSubviews NS_AVAILABLE_IOS(5_0); // Called just after the view controller‘s view‘s layoutSubviews method is invoked. Subclasses can implement as necessary. The default is a nop. - (void)viewDidLayoutSubviews NS_AVAILABLE_IOS(5_0); // 5. - (void)viewDidAppear:(BOOL)animated; // Called when the view has been fully transitioned onto the screen. Default does nothing
说明:
加载XIB的时候,我们同样可以不指定XIB名称,这样loadView 就会最终加载与控制器同名的 XIB (命名规范很重要啊)
DViewController *touch = [[DViewController alloc] init]; [self presentViewController:touch animated:YES completion:nil];
同时,如果我们删掉 DViewController.xib ,同时创建一个 DView.xib 当我们用以上不指定xib名称,同样是可以加载出来的(命名规范很重要)。
我们可以知道,加载xib的过程是,如果指定名称,那么加载指定名称的xib,如果没有指定名称就会加载和控制器同名的xib,如果没有就会找去控制器名相同但是没有 controller 的xib来加载。
- A present B控制器再返回,两个控制器的生命周期
1. 创建A控制器
流程:
A:loadView A:viewDidLoad A:viewWillAppear A:viewWillLayout... A:viewDidAppear
2. A present 到B控制器
流程:
A:loadView A:viewDidLoad A:viewWillAppear A:viewWillLayout... // 可能多次调用 A:viewDidAppear -------------- Present B控制器 -------------- B:loadView B:viewDidLoad A:viewWillDisappear B:viewWillAppear B:viewLayout.... // 可能多次调用 A;viewLayout... // 可能多次调用 B:viewDidAppear // 多次调用,会跟下面的调用顺序可能会有些调换 A:viewDidDisappear