iOS App 启动过程(三),本文介绍 main() 函数之后的过程以及 controller 与 view 的生命周期。
main函数后
进入 mian() 之后需要设置 AppDelegate 为应用代理,代理会在 App 启动之后调用:1
2[AppDelegate application:didFinishLaunchingWithOptions:] //程序完成加载
[AppDelegate applicationDidBecomeActive:] //程序被激活
点击Home键时
1 | [AppDelegate applicationWillResignActive:] //程序取消激活状态 |
点击APP时
1 | [AppDelegate applicationWillEnterForeground:] // 程序进入前台 |
UIViewController 的生命周期
1 | initWithCoder: |
initWithNibName:bundle:
非 StoryBoard 创建 UIViewController 会调用这个方法。不要在这里做 View 相关操作,View 在 loadView 方法中才初始化。
initWithCoder:
使用 StoryBoard 进行视图管理,StoryBoard 会自动初始化 UIViewController,方法 initWithNibName:bundle 不会被调用,initWithCoder 会被调用。
loadView
loadView 方法在 UIViewController 对象的 view 被访问且为空的时候调用。这是它与 awakeFromNib 方法的一个区别。在重写 loadView 方法的时候,不要调用父类的方法。self.view 是在 loadView 方法中创建并建立联系的,不要调用 [super loadView],要将自定义的 view 赋值给 self.view。如果该控制器没有 xib 文件,重写了 loadView 但没有做任何事情(也就是 self.view为空),在 viewDidLoad 中还使用了 self.view(self.view 为空时会调用 loadView),这样会造成死循环。
指定构造函数
UIViewController 有两个 Designated Initializer1
2initWithNibName: bundle:
initWithCoder:
UIView 的生命周期
当创建 view 时
1 | willMoveToSuperview: |
当view销毁时
1 | willMoveToWindow: |
注意:
只会执行一次的方法有 removeFromSuperview、dealloc 两个方法,可以在这两个方法中执行释放内存、移除观察者、定时器等。
willRemoveSubview 是在 dealloc 后面执行的。如果有多个子视图,willRemoveSubview 会循环执行,直到移除所有子视图。
1 | - (void)willMoveToSuperview:(nullable UIView *)newSuperview; |
这两个方法可以根据参数判断,nil 则为销毁,否则为创建;
1 | - (void)didMoveToSuperview; |
这两个方法可以根据 self.superview 判断,nil 则为销毁,否则为创建。
layoutSubviews 的触发条件
init初始化不会触发layoutSubviews,initWithFrame初始化时,当rect的值不为CGRectZero时会触发。addSubview会触发layoutSubviews。- 设置
view的 Frame 会触发layoutSubviews。 - 滚动一个
UIScrollView会触发layoutSubviews。 - 旋转
Screen会触发父UIView上的layoutSubviews。
setNeedsLayout,标记为需要重新布局,不立即刷新,在下一轮 runloop 结束前刷新,layoutSubviews 一定会被调用。layoutIfNeeded,如果有需要刷新的标记,立即调用 layoutSubviews;如果没有标记,不会调用 layoutSubviews。
指定构造函数
UIView 有两个 Designated Initializer1
2initWithFrame:
initWithCoder: