View Controller 生命周期总结

(零)前言

最近在找工作,想在IOS方面发展,以前在公司现学现用做过一个IOS应用,然后放下了一段长时间,很多细节的东西没深入研究,被鄙视了。现在只能一口一口地把IOS的知识细嚼透彻,闲话不多说,开始进入正题。


(一)源起

一开始学习View Controller生命周期都是去问度娘或谷大叔,不过回答基本都是差不多,感觉隔靴搔痒,触动不了痛点,于是只有亲手实践,边看文档,边看资料(斯坦福IOS视频,不错的教程),一边动手实践,来得出结论。


(二)环境

实践的环境是基于Xcode5,IOS7,storyboard


(三)viewDidLoad

下面先按照模板生成一个单页面工程,看看里面都有些什么。模板里面有两个方法,分别是viewDidLoad和didReceiveMemoryWarning,这里我们先研究viewDidLoad这个方法。



要弄清楚viewDidLoad这方法是干嘛的,其实最好的方法就是看文档,我们按照alt键,点击一下方法名,看看文档是怎么说的


我们可以看到,viewDidLoad方法,是在controller的view层级树(view有子view,子view又可能有子view,形成一个层次)全部加载到内存后才触发的。无论view层级树是从nib文件(storyboard)加载,还是手动在loadView创建的,之后都会调用viewDidLoad方法,这时候controller的view都已经全部加载到内存里面了,我们可以对view进行一些自定义操作,不过要留意,这时候的view还没真正绘制到界面上。viewDIdLoad方法只会被调用一次,我们可以将一些一次性的操作放到这里,例如变量的初始化等等。

(四)viewWillAppear 和 viewDidAppear

上面说到,触发viewDidLoad后,view实际上还没加载到界面上。于是乎,ios就给了这样一个方法,让我们可以在view加载到界面之前做一些自定义操作,例如根据当前设备的旋转方向或页面的样式来调整status bar响应的方向和样式,这个方法就是viewWillAppear,另外当view加载完成后,ios也会回调viewDidAppear方法,告诉我们view加载完成了


下面我们看看文档是怎么精确解析上面两个函数的,首先是viewWillAppear


通过阅读文档后,大家可能意识到,我之前说的“把view添加到界面上”这句话其实不太准确,准确来讲应该说是“把view添加到view层级树上去”。怎么理解这句话呢?首先看看这一幅图


IOS对界面的组织就像千层饼一样,一层一层地把view往上叠加,那么第一层、最初始的那层view是什么呢?那就是我们的window,我们看看下面这一段代码

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
    // Override point for customization after application launch.
    self.viewController = [[DMViewController alloc] initWithNibName:@"DMViewController" bundle:nil];
    self.window.rootViewController = self.viewController;
    [self.window makeKeyAndVisible];
    return YES;
}
第一行的self.window就是我们所说的第一层view。接下来其他controller的view都是直接或间接添加到window上的,这样就形成了一个层次关系,也就是文档所说的view hierarchy

(五)viewDidLoad引出的问题

似乎viewDidLoad的讨论就快结束了,其实还没,这里有一个问题,在viewDidLoad之前,我们的view,还有我们的view controller是怎么来的?

既然我们用到了storyboard,那答案肯定就在sotryboard里面,首先我们在storyboard添加多一个scene,并且把另一个scenc的custom class改为我新建的TViewController




我们以source code的形式打开Main.storyboard,会看到其实sotryboard就是一个xml文件,文件里面根据我们在Interface build的设计定义了各种的对象,例如我们看到的scene,viewcontroller,view等等,storyboard的工作就是把这些对象给序列化下来,保存起来,让后当程序运行的时候,就进行反序列化操作,生成对象(这就有点像Spring)。


按照ios的惯例,在以上这些对象被反序列化生成实例放入到内存后,应该会通知用户。没错,的确是有这样的方法,方法就是awakeFromNib,并且我们打断点观察,可以发现他们的调用顺序是如下图所示


不过别以为当系统回调awakeFromNib后,你就可以获得界面上的元素的引用了,其实这时候IBOutlet还没建立起来,要验证这个结论,我们我界面上拉一个button,并建立IBOutlet


然后在awakeFromNib里面获取这个引用,看看观察一下他的值


可以看到,引用为空,也就是这个时候虽然storyboard的内容已经实例化到内存里面,可是IBOutlet联系还没建立起来,所以如果在这里想对界面上的view进行操作,是没用的。不过具体是怎么建立,有没有方法回回调,这我暂时没找到答案。


(六)viewWillLayoutSubViews 和 viewDidLayoutSubviews

当view发生改变,要重新布局他的subviews前后,会调用以上两个方法,例如view第一次被加载时,页面发生旋转后,或者网view里面加入一个subview后,都回触发(具体的触发时机和机制要继续深入了解才能解析说明)



(七)总结




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值