(资料图片仅供参考)
首先明确两个概念:
UIWindow 对象 : 整个程序中视图层次结构中最顶层,充当一个容器类。UIViewController 对象 :viewController 中一个 view属性是 view层次结构中rootView,可以添加 view构建复杂的视图结构,通过生命周期方法loadView、viewDidLoad、viewWillAppear 等控制视图声明周期,因为他继承于 UIResponder,所以可以响应和处理用户事件。View、 Control 、 Layer 对象 :view可以通过 addSubView 和 removeFromSuperView等方法管理视图层次结构,使用 layoutSubviews、layoutIfNeeded 和 setNeedsLayout 等方法布局 view的层次结构,当系统提供的 view无法满足需要,可以重写 drawRect 方法或者通过 layer属性构造更加复杂的图形和动画。 iOS中布局相关方法 - (CGSize)sizeThatFits:(CGSize)size; - (void)sizeToFit; sizeToFit 自动调用 sizeThatFits 方法,不能在子类中重写 sizeToFit ---------------------------------------------------------------------- - (void)layoutSubViews; - (void)layoutIfNeeded; - (void)setNeedsLayout layoutSubviews 在以下情况下会被调用 init初始化不会触发 layoutSubviews,但是 initWithFrame 进行初始化会被调用,当 rect 的值不为 CGRectZero 时,也会触发。addSubView会触发 layoutSubviews设置 view的 frame 会触发 layoutSubviews滚动 ScrollView 时会触发 layoutSubviews旋转 Screen 会触发 父view 上的 layoutSubviews改变一个 view的大小也会触发父view的 layoutSubviews,所以重写这个方法要调用 [super layoutSubViews] setNeedsLayout 标记需要刷新布局的控件,下一次运行循环的时候会刷新布局,异步调用 layoutIfNeeded——>layoutIfNeeded,立即刷新布局——>layoutSubViews --------------------------------------------------------------------- - (void)setNeedsDisplay;- (void)drawRect; setNeedsDisplay 方法,标记为重绘,异步调用 drawRect 方法 drawRect 方法,重写此方法,执行重绘任务 这个两个方法都没没有递归,对 subViews 也不负责,只负责自己。 ---------------------------------------------------------------------
layoutSubviews对subviews重新布局
layoutSubviews方法调用先于drawRect
setNeedsLayout在receiver标上一个需要被重新布局的标记,在系统runloop的下一个周期自动调用layoutSubviews
layoutIfNeeded方法如其名,UIKit会判断该receiver是否需要layout.根据Apple官方文档,layoutIfNeeded方法应该是这样的
layoutIfNeeded遍历的不是superview链,应该是subviews链
drawRect是对receiver的重绘,能获得context
setNeedDisplay在receiver标上一个需要被重新绘图的标记,在下一个draw周期自动重绘,iphone device的刷新频率是60hz,也就是1/60秒后重绘