处理视图相关通知
当视图的可见性发⽣变化时,视图控制器会⾃动调⽤⼀系列⽅法来响应变化。
所有可能的状态、⽅法和状态之间的转换关系在下图中被明确标出。
可以看到每⼀个will⽅法都有⾃⼰对应的did⽅法。但是如果我们在will⽅法中开始⼀个任务,不仅要在对应的did⽅法中结束它,还要考虑到和这个will⽅法相反的那个will⽅法(注意到Appearing和Disappearing这两个状态是可以互相转化的)
可以看到每⼀个will⽅法都有⾃⼰对应的did⽅法。但是如果我们在will⽅法中开始⼀个任务,不仅要在对应的did⽅法中结束它,还要考虑到和这个will⽅法相反的那个will⽅法(注意到Appearing和Disappearing这两个状态是可以互相转化的)
在运⾏时展⽰View
UIKit极⼤的简化了加载和展⽰View的过程,它⼤概会按照以下顺序执⾏⼀些任务:
1.通过storyboard⽂件中的信息实例化视图
2.连接outlet和action
3.把根视图赋值给UIViewController的view
属性(其实就是调⽤loadView⽅法)
4.调⽤UIViewController的awakeFromNib⽅法。要注意,在调⽤⽅法前,的trait collecion为空且⼦视图的位置可能不正确
5.调⽤UIViewController的viewDidLoad⽅法。
此时已经完成了视图的加载⼯作,在展⽰到屏幕之前,还有以下⼏个步骤:
1.调⽤UIViewController的viewWillAppear⽅法。
2.更新视图的布局
3.把视图展⽰到屏幕上
4.调⽤UIViewController的viewDidAppear⽅法。
awakeFromNib⽅法
⾄此,第⼀个问题已经⼏乎解释完了,还剩⼀个awakeFromNib⽅法。
我们已经知道,awakeFromNib⽅法被调⽤时,所有视图的outlet和action已经连接,但还没有被确定。这个⽅法可以算作是和视图控制器的实例化配合在⼀起使⽤的,因为有些需要根据⽤户喜好来进⾏设置的内容,⽆法存在storyboard中,所以可以在awakeFromNib
⽅法中被加载进来。
awakeFromNib⽅法在视图控制器的⽣命周期内只会被调⽤⼀次。因为它和视图控制器从nib⽂件中的解档密切相关,和view的关系却不⼤。
具体⽅法的解释
loadView⽅法
当执⾏到loadView⽅法时,视图控制器已经从nib⽂件中被解档并创建好了,接下来的任务主要是对view进⾏初始化。
loadView⽅法在UIViewController对象的view属性被访问到且为空的时候调⽤。这是它与awakeFromNib⽅法的⼀个区别。假设我们在处理内存警告时释放view属性(其实并不应该这么做,这⾥举个例⼦):self.view = nil。因此loadView⽅法在视图控制器的⽣命周期内可能会被多次调⽤。
这个⽅法不应该被直接调⽤,⽽是由系统⾃动调⽤。它会加载或创建⼀个view并把它赋值给UIViewController的view属性。在创建view的过程中,⾸先会根据nibName去对应的Nib⽂件然后加载。如果nibName为空,或不到对应的Nib⽂件,则会创建⼀个空视图(这种情况⼀般是纯代码,也就是为什么说代码构建View的时候,要重写loadView⽅法)。
注意在重写loadView⽅法的时候,不要调⽤⽗类的⽅法。viewDidLoad⽅法loadView⽅法执⾏完之后,就会执⾏viewDidLoad⽅法。此时整个视图层次(view hierarchy)已经被放到内存中。⽆论是从nib⽂件加载,还是通过纯代码编写界⾯,viewDidLoad⽅法都会执⾏。我们可以重写这个⽅法,对通过nib⽂件加载的view做⼀些其他的初始化⼯作。⽐如可以移除⼀些视图,修改约束,加载数据等。
view WillAppea r和view DidAppea r⽅法
在视图加载完成,并即将显⽰在屏幕上时,会调⽤viewWillAppear⽅法,在这个⽅法⾥,可以改变当前屏幕⽅向或状态栏的风格等。当viewWillAppear
⽅法执⾏完后,系统会执⾏viewDidAppear⽅法。在这个⽅法中,还可以对视图做⼀些关于展⽰效果⽅⾯的修改。
视图的⽣命历程
到⽬前为⽌,我们已经了解了每个⽅法的作⽤,接下来就把整个流程梳理⼀遍。
1. -[ViewController initWithCoder:]或-[ViewController initWithNibName:Bundle]:⾸先从归档⽂件中加载UIViewController对象。即使是
view ui框架纯代码,也会把nil作为参数传给后者。
2. -[UIView awakeFromNib]:作为第⼀个⽅法的助⼿,⽅便处理⼀些额外的设置。
3. -[ViewController loadView]:创建或加载⼀个view并把它赋值给UIViewController的view属性
4. -[ViewController viewDidLoad]:此时整个视图层次(view hierarchy)已经被放到内存中,可以移除⼀些视图,修改约束,加载数据等
5. -[ViewController viewWillAppear:]:视图加载完成,并即将显⽰在屏幕上,还没有设置动画,可以改变当前屏幕⽅向或状态栏的风格等。
6. -[ViewController viewWillLayoutSubviews]:即将开始⼦视图位置布局
7. -[ViewController viewDidLayoutSubviews]:⽤于通知视图的位置布局已经完成
8. -[ViewController viewDidAppear:]:视图已经展⽰在屏幕上,可以对视图做⼀些关于展⽰效果⽅⾯的修改。
9. -[ViewController viewWillDisappear:]:视图即将消失
10. -[ViewController viewDidDisappear:]:视图已经消失
如果考虑UIViewController可能在某个时刻释放整个view。那么再次加载视图时显然会从步骤3开始。因为此时的UIViewController对象依然存在。
总结
1. 只有init系列的⽅法,如initWithNibName需要⾃⼰调⽤,其他⽅法如loadView和awakeFromNib则是系统⾃动调⽤。⽽viewWill/Did系列的⽅
法则类似于回调和通知,也会被⾃动调⽤。
2. 纯代码写视图布局时需要注意,要⼿动调⽤loadView⽅法,⽽且不要调⽤⽗类的loadView⽅法。纯代码和⽤IB的区别仅存在于loadView⽅法
及其之前,编程时需要注意的也就是loadView⽅法。
3. 除了initWithNibName和awakeFromNib⽅法是处理视图控制器外,其他⽅法都是处理视图。这两个⽅法在视图控制器的⽣命周期⾥只会调⽤
⼀次。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论