main函数后
进入 mian()
之后需要�设置 AppDelegate
为应用代理,代理会在 App 启动之后调用:
[AppDelegate application:didFinishLaunchingWithOptions:] //程序完成加载
[AppDelegate applicationDidBecomeActive:] //程序被激活
点击Home键时
[AppDelegate applicationWillResignActive:] //程序取消激活状态
[AppDelegate applicationDidEnterBackground:] // 程序进入后台
点击APP时
[AppDelegate applicationWillEnterForeground:] // 程序进入前台
[AppDelegate applicationDidBecomeActive:] // 程序被激活
UIViewController 的生命周期
initWithCoder:
awakeFromNib
loadView
viewDidLoad
viewWillAppear:
viewWillLayoutSubviews
viewDidLayoutSubviews
viewDidAppear:
viewWillDisappear:
viewDidDisappear:
dealloc
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 Initializer
initWithNibName: bundle:
initWithCoder:
UIView 的生命周期
当创建 view 时
willMoveToSuperview:
didMoveToSuperview
willMoveToWindow:
didMoveToWindow
layoutSubviews
drawRect:
当view销毁时
willMoveToWindow:
didMoveToWindow
willMoveToSuperview:
didMoveToSuperview
removeFromSuperview
dealloc
注意:
只会执行一次的方法有 removeFromSuperview
、dealloc
两个方法,可以在这两个方法中执行释放内存、移除观察者、定时器等。
willRemoveSubview
是在 dealloc
后面执行的。如果有多个子视图,willRemoveSubview
会循环执行,直到移除所有子视图。
- (void)willMoveToSuperview:(nullable UIView *)newSuperview;
- (void)willMoveToWindow:(nullable UIWindow *)newWindow;
这两个方法可以根据参数判断,nil
则为销毁,否则为创建;
- (void)didMoveToSuperview;
- (void)didMoveToWindow;
这两个方法可以根据 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 Initializer
initWithFrame:
initWithCoder: