控制器加载底层原理和UI初始化过程

一、控制器的初始化过程:

1、两种初始化方式: xib和纯代码。
2、
- (instancetype)init{} -- 代码初始化方法
- (instancetype)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil{}-- xib初始化方法

(1)init 方法中封装了 initWithNibName 方法;
(2)nibNameOrNil 如果为nil,默认去找类名相同的xib文件;nibBundleOrNil 如果为nil,默认去找 mainBundle。
也可以指定xib文件进行加载。
(3)所以我们在写一些初始化逻辑,尽量写在 initWithNibName 方法中。

二、控制器中的View 初始化过程:

- (void)loadView{}
(1)这个方法时控制器中的View 初始化方法,默认是执行的。
(2)控制器中的View(self.view)能不能指定呢??
在 loadView方法中重新给 self.view 赋值, 指定为我们自定义的View即可!(不要执行 [super loadView]!!!)
这样做的好处就是: 控制器和View分离,所谓C弱化。(MVCS 就是利用这种处理) 结合KVO, 在C中处理View中的业务~
(3)空实现此方法,并在viewDidLoad方法中执行self.view,会造成死循环!!!
因为 self.view 是一个懒加载过程。调用self.view 时,会执行loadView,此时返回为nil。又执行viewDidLoad -> self.view -> loadView -> viewDidLoad ...
(4)View 的初始化方式:
a. 纯代码布局:
- (instancetype)init{}
- (instancetype)initWithFrame:(CGRect)frame{}
view纯代码布局的初始化过程, init方法中封装了 initWithFrame, 尽量把初始化代码写在 initWithFrame 中。
b.xib布局:
- (instancetype)initWithCoder:(NSCoder *)aDecoder{}
- (void)awakeFromNib{}
xib文件布局view, 初始化方法执行 initWithCoder,然后执行 awakeFromNib

三、布局问题:

1、控制器:
- (void)viewWillLayoutSubviews{ }
在xib布局时,viewDidLoad viewWillAppear 中的self.view 大小都不是屏幕的大小,在 viewWillLayoutSubviews 方法中,才是真正屏幕大小。
可以把布局代码移动这个方法中,解决布局中的bug。
2、view:
- (void)layoutSubviews{} 这里去修改子控件的布局

setNeedsLayout:会调用对象的 layoutSubviews 方法,但是不会立即执行,用runloop解释,就是在当前循环结束时,下一个循环去执行,暂时标记而已。这样做的好处是界面可以统一刷新,提高性能。
layoutIfNeeded:会调用对象的 layoutSubviews 方法,并且立即执行。
setNeedsDisplay:会调用对象的 drawRect 方法,也是不会立即执行,原理同setNeedsLayout相同。

四、drawRect 方法:

- (void)drawRect:(CGRect)rect {}
UIGraphicsPushContext(context2);
UIGraphicsPopContext();

1、stack 存放上下文的栈, 默认是没有的 push一个context存一个。正常不对这个栈进行操作。
2、上下文跟CALayer是有关系的,修改context会渲染到CALayer上去。

五、可视化

IB_DESIGNABLE:
IBInspectable:
开发中很少使用,知道就好。

你可能感兴趣的:(控制器加载底层原理和UI初始化过程)