首页 > 代码库 > UIViewController的生命周期
UIViewController的生命周期
ViewController生命周期
alloc ->init-> initWithNibName -> loadView -> viewDidLoad -> viewWillAppear -> viewDidAppear -> viewWillDisappear -> viewDidDisappear -> dealloc
注意viewWillUnload和viewDidUnload已经在ios6被废弃了,因为Clearing references to views is no longer necessary。
注意1.没有viewWillLoad。
注意2.viewDidLoad和viewDidUnload并不是成对的。
ViewController是IOS开发中MVC模式中的C,ViewController是view的controller,ViewController的职责主要包括管理内部各个view的加载显示和卸载,同时负责与其他ViewController的通信和协调。在IOS中,有两类ViewController,一类是显示内容的,比如UIViewController、UITableViewController等,同时还可以自定义继承自UIViewController的ViewController;另一类是ViewController容器,UINavigationViewController和UITabBarController等,UINavigationController是以Stack的形式来存储和管理ViewController,UITabBarController是以Array的形式来管理ViewController。和Android中Activity一样,IOS开发中,ViewController也有自己的生命周期(Lifecycle)。
View的加载过程,如下图:
从图中可以看到,在view加载过程中首先会调用loadView方法,在这个方法中主要完成一些关键view的初始化工作,比如UINavigationViewController和UITabBarController等容器类的ViewController;接下来就是加载view,加载成功后,会接着调用viewDidLoad方法,这里要记住的一点是,在loadView之前,是没有view的,也就是说,在这之前,view还没有被初始化。完成viewDidLoad方法后,ViewController里面就成功的加载view了,如上图右下角所示。
在Controller中创建view有两种方式,一种是通过代码创建、一种是通过Storyboard或Interface Builder来创建,后者可以比较直观的配置view的外观和属性,Storyboard配合IOS6后推出的AutoLayout,应该是Apple之后主推的一种UI定制解决方案,通过IB或Storyboard创建view,在Controller中创建view后,会在Controller中对view进行一些操作,会出现如下代码:
视图的加载过程
AppDelegate.m
RootViewController *rootViewController = [[RooViewController alloc] init]; // 1
self.window.rootViewController = rootViewController; // 9
[rootViewController release];
-(id)init
{
self = [super init]; // 2 里面用到了一个指定初始化方法指定到下面
if(self){ // 5
//NSLog(@"%@",self.view); //在创建视图控制器时,不要在视图控制器的初始化方法中做view相关的事情,一般在init方法中初始化一些数据,模型
}
return self; // 6
}
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; // 3
if (self) {
// Custom initialization
}
return self; // 4
}
一旦覆盖loadView,一定要创建一个视图给视图控制器,可以调用父类的loadview或者自定义一个view,否则的话我们视图的创建是失败的,有可能会引发循环调用的问题
- (void)loadView // 7
{
//第一种方式:调用父类的loadview
[super loadview];
//第二种方式:自定义
UIView *view = [[UIView alloc] initWIthFrame:[[UIScreen mainScreen] appllicationFrame]];
view.backgroundColor = [UIcolor redColor];
self.view = view;
[view release];
// add subview
}
- (void)viewDidLoad // 8
{
[super viewDidLoad];
// 1.view -> nil 2.getter method
// NSLog(@"%@",self.view);
// 访问网络
}
// 视图的出现与消失
-(void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:(BOOL)animated];
}
-(void)viewDidAppear:(BOOL)animated{
[super viewDidAppear:(BOOL)animated];
}
// 视图的卸载(6.0之前)
从图中可以看到,当系统发出内存警告时,会调用didReceiveMemoeryWarning方法,如果当前有能被释放的view,系统会调用viewWillUnload方法来释放view,完成后调用viewDidUnload方法,至此,view就被卸载了。此时原本指向view的变量要被置为nil,具体操作是在viewDidUnload方法中调用self.myButton = nil;
SecondViewController.h
@interface SecondViewController:UIViewController
@property (nonatomic,retain) UIView *subView;
@end
SecondViewController.m
- (void) loadView
{
UIView *baseView = [[UIView alloc]initWIthFrame:[[UIScreen mainScreen] appllicationFrame]]; // 1
baseView.backgroundColor = [UIColor yellowColor];
self.view = baseView;
[baseView release];
// 全局的不要在下面release,他还要给其他人用
_subView = [[UIView alloc] initWithFreame:CGRect(60,100,200,200)]; // 1
_subView.backgroundColor = [UIColor redColor];
[self.view addSubview:_subView]; // 2
// 局部变量出了这个方法就没了,意义在于给self.view
UIView *otherView = [[UIView alloc]initWIthFrame:CGRect(110,350,100,100)]; // 1
otherView.backgroundColor = [UIColor yellowColor];
[self.view addSubview:otherView]; // 2
[otherView release]; // 1
}
- (void) viewWillUnload // 5.0~6.0 这里的view实际上指的就是baseView
{
[super viewWillUnload];
}//视图控制器的视图将要卸载(这行过后视图控制器的view为nil)
- (void) viewDidUnload // 卸载时,self.view为nil会release一次subView,之后调用self.subView = nil再释放一次。
{
[super viewDidUnload];
// 系统自己判断了,然后释放了self.view -> nil 自己会release,会把它所加的对象都release一遍(otherView也会死掉) //1
self.subView = nil; // 0
// NSLog(@"%@",self.view); 不能这样做,因为self.view -> nil getter方法 会引发[self loadView];
} // 视图控制器已经卸载,需要卸载掉其他的子视图(强引用)
- (void)didReceiveMemoryWarning // 6.0之后用这个
{
[super didReceiveMemoryWarning];
// 拿到应用程序的窗口
// [UIApplication sharedApplication].keyWindow; 或 self.view.window (window指AppDelegate里面创建的window,只有一个window)
// NSLog(@"self.view.window : %@",self.view.window); 如果出现内存警告,则view已经deal,所以不能打印这句话
if ([self.view window] == nil)// 当前的视图控制器中的视图不在当前窗口中
{
self.subView = nil;
self.view = nil; // 6.0之前会帮我们写,之后要自己写
}
}
- (void) dealloc
{
self.subView = nil;
[super dealloc];
}
@property(nonatomic,retain) UIView *view; // The getter first invokes [self loadView] if the view hasn‘t been set yet. Subclasses must call super if they override the setter or getter.
如果这个视图view尚未设置或初始化,那么只要第一次调用getter方法就会引发[self loadView]
- (void)loadView; // This is where subclasses should create their custom view hierarchy if they aren‘t using a nib. Should never be called directly.
如果没有用nib来创建的话,他会创建一个自定义的有层次结构的视图。
1、alloc 创建对象,分配空间
2、init (initWithNibName) 初始化对象,初始化数据
3、loadView 当手动创建时,需要覆盖这个方法,如果 从nib载入视图,通常这一步不需要去干涉。除非你没有使用xib文件创建
4、viewDidLoad 载入完成,可以进行自定义数据以及动态创建其他控件,加载网络请求的数据
5、viewWillAppear 视图将出现在屏幕之前,马上这个视图就会被展现在屏幕上了
6、viewDidAppear 视图已在屏幕上渲染完成
当一个视图被移除屏幕并且销毁的时候的执行顺序,这个顺序差不多和上面的相反
1、viewWillDisappear 视图将被从屏幕上移除之前执行
2、viewDidDisappear 视图已经被从屏幕上移除,用户看不到这个视图了
3、viewUnLoad
4、dealloc 视图被销毁,此处需要对你在init和viewDidLoad中创建的对象进行
loadView和viewDidLoad的区别就是,loadView时view还没有生成,viewDidLoad时,view已经生成了,loadView只会被调用一次,而viewDidLoad可能会被调用多次(View可能会被多次加载),当view被添加到其他view中之前,会调用viewWillAppear,之后会调用viewDidAppear。当view从其他view中移除之前,调用viewWillDisAppear,移除之后会调用viewDidDisappear。当view不再使用时,受到内存警告时,ViewController会将view释放并将其指向为nil。
UIViewController的生命周期