UIViewController和UIView不同加载方式的生命周期函数

1 基本说明

话说做了iOS几年,对于UIViewController和UIView的生命周期函数一直不是很重视,导致了很多模糊的地方。今天专门写一个Demo来验证一下,发现不同加载方式差别还是蛮大的。具体Demo地址UIViewController和UIView生命周期加载和卸载

2 加载UIViewController

每一种加载方式所调用的加载方法不同,而且还有一些细节地方不同。苹果为我们提供了四种默认的加载方式,不过我是纯代码党,AutoLayout以后,我们通过Masonry这个第三方布局利器来布局,在我Git上也有专门总结的不同布局解决方案。接下来我们看看系统的四种方式,犹豫没有什么理论性的东西,我就直接上代码为主了:

  • 通过XIB加载。
  • 通过StoryBoard加载。
  • 通过NSCoding协议加载。
  • 通过代码加载。

2.1 用XIB加载UIViewController

首先看初始化代码:

- (IBAction)loadControllerFromXIB:(id)sender {
    XIBViewController *xibVC = [[XIBViewController alloc]initWithNibName:@"XIBViewController" bundle:[NSBundle mainBundle]];
    [self.navigationController pushViewController:xibVC animated:YES];
}

当我们不实现loadView的时候打印结果:

2017-04-15 12:05:32.974 UIViewController和UIView生命周期加载和卸载[59883:1192231] initWithNibName
2017-04-15 12:05:32.987 UIViewController和UIView生命周期加载和卸载[59883:1192231] viewDidLoad
2017-04-15 12:05:32.987 UIViewController和UIView生命周期加载和卸载[59883:1192231] viewWillAppear
2017-04-15 12:05:32.996 UIViewController和UIView生命周期加载和卸载[59883:1192231] viewWillLayoutSubviews
2017-04-15 12:05:32.997 UIViewController和UIView生命周期加载和卸载[59883:1192231] viewDidLayoutSubviews
2017-04-15 12:05:33.002 UIViewController和UIView生命周期加载和卸载[59883:1192231] viewWillLayoutSubviews
2017-04-15 12:05:33.002 UIViewController和UIView生命周期加载和卸载[59883:1192231] viewDidLayoutSubviews
2017-04-15 12:05:33.506 UIViewController和UIView生命周期加载和卸载[59883:1192231] viewDidAppear
2017-04-15 12:05:37.142 UIViewController和UIView生命周期加载和卸载[59883:1192231] clickButton
//pop以后
2017-04-15 12:05:42.334 UIViewController和UIView生命周期加载和卸载[59883:1192231] viewWillDisappear
2017-04-15 12:05:42.837 UIViewController和UIView生命周期加载和卸载[59883:1192231] viewDidDisappear
2017-04-15 12:05:42.838 UIViewController和UIView生命周期加载和卸载[59883:1192231] dealloc

我发现一个很奇怪的现象。如果用XIB加载的控制器,并且实现了一个空loadView,那么我们在XIB设置的视图都失效了,应该是系统返回了一个默认的视图覆盖了。但是用Storyboard加载的视图,实现一个空的loadView则不会丢失Storyboard里面的视图,这个是用XIB和Storyboard的一个注意点

-(void)loadView{
    [super loadView];
    NSLog(@"loadView");
}

2.2 用Storyboard加载UIViewController

初始化代码:

- (IBAction)laodControllerFromSB:(id)sender {
    UIStoryboard *sb = [UIStoryboard storyboardWithName:@"Second" bundle:[NSBundle mainBundle]];
    SBViewController *sbVC = [sb instantiateViewControllerWithIdentifier:@"SBViewController"];
    [self.navigationController pushViewController:sbVC animated:YES];
}

运行结果:

2017-04-15 12:26:45.364 UIViewController和UIView生命周期加载和卸载[59932:1194239] initWithCoder
2017-04-15 12:26:45.365 UIViewController和UIView生命周期加载和卸载[59932:1194239] awakeFromNib
2017-04-15 12:26:45.368 UIViewController和UIView生命周期加载和卸载[59932:1194239] loadView
2017-04-15 12:26:45.368 UIViewController和UIView生命周期加载和卸载[59932:1194239] viewDidLoad
2017-04-15 12:26:45.368 UIViewController和UIView生命周期加载和卸载[59932:1194239] viewWillAppear
2017-04-15 12:26:45.372 UIViewController和UIView生命周期加载和卸载[59932:1194239] viewWillLayoutSubviews
2017-04-15 12:26:45.373 UIViewController和UIView生命周期加载和卸载[59932:1194239] viewDidLayoutSubviews
2017-04-15 12:26:45.877 UIViewController和UIView生命周期加载和卸载[59932:1194239] viewDidAppear
//pop以后
2017-04-15 12:26:50.669 UIViewController和UIView生命周期加载和卸载[59932:1194239] viewWillDisappear
2017-04-15 12:26:51.172 UIViewController和UIView生命周期加载和卸载[59932:1194239] viewDidDisappear
2017-04-15 12:26:51.172 UIViewController和UIView生命周期加载和卸载[59932:1194239] dealloc

对于Storyboard,使用一个空的loadView没有影响。

2.3 用NSCodeing加载UIViewController

初始化代码:

//这里我就不实现NSCoding协议了,直接传入一个nil参数。
- (IBAction)loadControllerFromCoder:(id)sender {
    CoderViewController *coderVC = [[CoderViewController alloc]initWithCoder:nil];
    [self.navigationController pushViewController:coderVC animated:YES];
}

运行结果:

2017-04-15 12:30:25.962 UIViewController和UIView生命周期加载和卸载[59932:1194239] initWithCoder
2017-04-15 12:30:25.963 UIViewController和UIView生命周期加载和卸载[59932:1194239] loadView
2017-04-15 12:30:25.963 UIViewController和UIView生命周期加载和卸载[59932:1194239] viewDidLoad
2017-04-15 12:30:25.963 UIViewController和UIView生命周期加载和卸载[59932:1194239] viewWillAppear
2017-04-15 12:30:25.967 UIViewController和UIView生命周期加载和卸载[59932:1194239] viewWillLayoutSubviews
2017-04-15 12:30:25.967 UIViewController和UIView生命周期加载和卸载[59932:1194239] viewDidLayoutSubviews
2017-04-15 12:30:25.968 UIViewController和UIView生命周期加载和卸载[59932:1194239] viewWillLayoutSubviews
2017-04-15 12:30:25.968 UIViewController和UIView生命周期加载和卸载[59932:1194239] viewDidLayoutSubviews
2017-04-15 12:30:26.470 UIViewController和UIView生命周期加载和卸载[59932:1194239] viewDidAppear
//pop以后
2017-04-15 12:30:28.034 UIViewController和UIView生命周期加载和卸载[59932:1194239] viewWillDisappear
2017-04-15 12:30:28.537 UIViewController和UIView生命周期加载和卸载[59932:1194239] viewDidDisappear
2017-04-15 12:30:28.537 UIViewController和UIView生命周期加载和卸载[59932:1194239] dealloc

2.4 用代码加载UIViewController

初始化代码:

- (IBAction)loadControllerWithNone:(id)sender {
    CodeViewController *codeVC = [[CodeViewController alloc]init];
    [self.navigationController pushViewController:codeVC animated:YES];
}

运行结果:

2017-04-15 12:31:48.785 UIViewController和UIView生命周期加载和卸载[59932:1194239] initWithNibName
2017-04-15 12:31:48.786 UIViewController和UIView生命周期加载和卸载[59932:1194239] init
2017-04-15 12:31:48.787 UIViewController和UIView生命周期加载和卸载[59932:1194239] loadView
2017-04-15 12:31:48.787 UIViewController和UIView生命周期加载和卸载[59932:1194239] viewDidLoad
2017-04-15 12:31:48.788 UIViewController和UIView生命周期加载和卸载[59932:1194239] viewWillAppear
2017-04-15 12:31:48.792 UIViewController和UIView生命周期加载和卸载[59932:1194239] viewWillLayoutSubviews
2017-04-15 12:31:48.792 UIViewController和UIView生命周期加载和卸载[59932:1194239] viewDidLayoutSubviews
2017-04-15 12:31:48.792 UIViewController和UIView生命周期加载和卸载[59932:1194239] viewWillLayoutSubviews
2017-04-15 12:31:48.792 UIViewController和UIView生命周期加载和卸载[59932:1194239] viewDidLayoutSubviews
2017-04-15 12:31:49.293 UIViewController和UIView生命周期加载和卸载[59932:1194239] viewDidAppear
//pop以后
2017-04-15 12:31:55.594 UIViewController和UIView生命周期加载和卸载[59932:1194239] viewWillDisappear
2017-04-15 12:31:56.098 UIViewController和UIView生命周期加载和卸载[59932:1194239] viewDidDisappear
2017-04-15 12:31:56.098 UIViewController和UIView生命周期加载和卸载[59932:1194239] dealloc

3 加载UIView

3.1 用XIB加载UIView

初始化代码:

- (IBAction)loadViewFromXib:(id)sender {
    XibView *xibView = [[[NSBundle mainBundle]loadNibNamed:@"XIBView" owner:self options:nil] lastObject];
    [self.view addSubview:xibView];
}

运行结果:

2017-04-15 12:33:22.194 UIViewController和UIView生命周期加载和卸载[59932:1194239] initWithCoder
2017-04-15 12:33:22.195 UIViewController和UIView生命周期加载和卸载[59932:1194239] awakeFromNib
2017-04-15 12:33:22.195 UIViewController和UIView生命周期加载和卸载[59932:1194239] willMoveToWindow
2017-04-15 12:33:22.195 UIViewController和UIView生命周期加载和卸载[59932:1194239] willMoveToSuperview
2017-04-15 12:33:22.196 UIViewController和UIView生命周期加载和卸载[59932:1194239] didMoveToWindow
2017-04-15 12:33:22.196 UIViewController和UIView生命周期加载和卸载[59932:1194239] didMoveToSuperview
2017-04-15 12:33:22.197 UIViewController和UIView生命周期加载和卸载[59932:1194239] layoutSubviews
//这里是点击移除以后
2017-04-15 12:33:25.769 UIViewController和UIView生命周期加载和卸载[59932:1194239] willMoveToSuperview
2017-04-15 12:33:25.770 UIViewController和UIView生命周期加载和卸载[59932:1194239] willMoveToWindow
2017-04-15 12:33:25.771 UIViewController和UIView生命周期加载和卸载[59932:1194239] didMoveToWindow
2017-04-15 12:33:25.771 UIViewController和UIView生命周期加载和卸载[59932:1194239] didMoveToSuperview
2017-04-15 12:33:25.771 UIViewController和UIView生命周期加载和卸载[59932:1194239] dealloc

3.2 用代码加载UIView

初始化代码:

- (IBAction)loadViewWithNone:(id)sender {
    CodeView *codeView = [[CodeView alloc]init];
    codeView.backgroundColor = [UIColor greenColor];
    codeView.frame = CGRectMake(0, 500, 100, 50);
    [self.view addSubview:codeView];
}

运行结果:

2017-04-15 12:38:57.562 UIViewController和UIView生命周期加载和卸载[60323:1208772] initWithFrame
2017-04-15 12:38:57.562 UIViewController和UIView生命周期加载和卸载[60323:1208772] init
2017-04-15 12:38:57.562 UIViewController和UIView生命周期加载和卸载[60323:1208772] willMoveToWindow
2017-04-15 12:38:57.563 UIViewController和UIView生命周期加载和卸载[60323:1208772] willMoveToSuperview
2017-04-15 12:38:57.563 UIViewController和UIView生命周期加载和卸载[60323:1208772] didMoveToWindow
2017-04-15 12:38:57.563 UIViewController和UIView生命周期加载和卸载[60323:1208772] didMoveToSuperview
2017-04-15 12:38:57.564 UIViewController和UIView生命周期加载和卸载[60323:1208772] layoutSubviews
//点击移除以后
2017-04-15 12:39:02.751 UIViewController和UIView生命周期加载和卸载[60323:1208772] willMoveToSuperview
2017-04-15 12:39:02.752 UIViewController和UIView生命周期加载和卸载[60323:1208772] willMoveToWindow
2017-04-15 12:39:02.752 UIViewController和UIView生命周期加载和卸载[60323:1208772] didMoveToWindow
2017-04-15 12:39:02.752 UIViewController和UIView生命周期加载和卸载[60323:1208772] didMoveToSuperview
2017-04-15 12:39:02.752 UIViewController和UIView生命周期加载和卸载[60323:1208772] 点击移除
2017-04-15 12:39:02.753 UIViewController和UIView生命周期加载和卸载[60323:1208772] dealloc

4 总结

UIViewController不同加载方式钩子函数总结:

  • XIB加载方式
    • initWithNibName
    • loadView(注意:如果实现一个空的方法,则XIB设置的属性无效,会覆盖XIB中的设置)
    • viewDidLoad
  • Storyboard加载方式
    • initWithCoder
    • awakeFromNib
    • loadView(实现是一个空方法或者不实现没有影响)
    • viewDidLoad
  • NSCoding加载方式
    • initWithCoder
    • loadView
    • viewDidLoad
  • 代码加载方式
    • initWithNibName
    • init(这个是我初始化的时候主动调用,如果用initWithNibName传入nil参数则不会调用)
    • loadView
    • viewDidLoad

我们可以发现,代码加载方式和XIB加载方式一模一样,如果有XIB则加载XIB,如果没有XIB则可以代码添加视图。

UIView不同加载方式钩子函数总结:

  • XIB加载方式
    • initWithCoder
    • awakeFromNib
    • willMoveToWindow
  • 代码加载方式
    • initWithFrame(设置frame。)
    • init(init方法调用)
    • willMoveToWindow

我们发现,如果通过init初始化,然后手动设置Frame。则会导致上面的调用顺序。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,684评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,143评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,214评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,788评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,796评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,665评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,027评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,679评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 41,346评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,664评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,766评论 1 331
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,412评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,015评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,974评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,203评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,073评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,501评论 2 343

推荐阅读更多精彩内容