View and Window Architecture
View Hierarchies and Subview Management
- 父视图维护着一个子视图数组,数组最后一个元素就是父视图内顶部的视图
The View Drawing Cycle
- 不改变视图内容不会调用重绘代码
- 改变视图内容不会马上进行重绘,需要调用
setNeddsDisplay
或者setNeddsDisplayInRect
,这两个方法会告诉系统需要重绘,系统会在当前 runloop 结束以后开始重绘,这段时间还可以进行更改 - 改变视图的形状也不会调用重绘代码,只有当设置
contentMode
属性为UIViewContentModeRedraw
时才会调用
View Geometry and Coordinate Systems
- iOS坐标系原点是左上角,向右是 X 轴,向下是 Y 轴,UIWindows 和 UIView 有方法可以将一个坐标系转换到另一个坐标系
The Relationship of the Frame, Bounds, and Center Properties
- frame 指的是在父视图坐标系中指定了位置和大小,设置该值影响 bounds 和 center
- bounds 指的是在自己的坐标系中指定了大小,设置该值影响 frame
- center 指的是在父视图坐标系中指定一个点作为自己的中心点,设置该值影响frame
- 子视图超出父视图的区域可以使用
clipsTobounds
消除
Tips for Using Views Effectively
- 尽量减少绘制
- 不设置
contentMode
属性为UIViewContentModeRedraw
- 设置视图为不透明
- 滚动会在短时间内产生大量的视图更新,建议在滚动时可以改变 contentMode 属性或者暂时改变呈现内容的质量
- 不在视图中嵌入自定义视图,比如按钮中嵌入一个自定义图片
Views
Tweaking the Layout of Your Views Manually
- 当 view 的 size 改变时,会调用
layoutSubviews
方法 - 在滚动时会频繁 layoutsubview,当滚动事件开始,跟视图调用
setNeedsLayout
,layoutSubviews
方法会根据偏移量来更改视图位置 - 在写布局代码时,注意以下两点
- 改变设备方向时
- 状态栏高度改变,例如打电话时状态栏高度会增加
Interacting with Core Animation Layers
- 每个 view 的 layerClass 默认是 CALayer,可以通过重写
layerClass
方法来返回其他的 layer,例如你使用了大范围的滚动区域,你可以使用CATiledLayer
类 - view 的 delegate 指向他自身的 layer
- layer 不接收事件也不参与响应链