10th,May,2016
前言
UIView职责:
(1). 绘制和动画
(2). 布局和子视图管理
(3). 事件处理
绘制和动画
绘制像素到屏幕上
离屏渲染(OffScreen Rendering):
相关概念
初始化方法Method to override
- initWithFrame: 从代码加载视图
- initWithCoder: 从xib文件加载视图.(先调用initWithCoder,然后发送-awakeFromNib消息给nib中的每个对象)
- layerClass:if you want your view to use a different Core Animation layer for its backing store.
awakeFromNib 从xib或者storyboard加载完毕就会调用,当.nib文件被加载的时候,会发发送awakeFromNib的消息给nib文件中的每个对象,每个对象都可以重写awakeFromNib响应该消息。
frame , bounds 与 center
(1). frame: 当前视图在父视图中的位置和大小
(2). bounds: 当前视图在自身坐标系统中的位置和大小
(3). center: 当前视图的中心店在父视图中的位置
一般来说,通过frame属性设置视图的大小和位置,使用center或者frame改变视图的位置。
- (CGRect)frame {
return CGRectMake(self.frame.origin.x, self.frame.origin.y, self.frame.size.width, self.frame.size.height)
}
- (CGRect)bounds {
return CGRectMake(0, 0, self.frame.size.width, self.frame.size.height)
}
观察视图相关的变化Observing View-related Changes
The window property may be nil by the time that this method is called, indicating that the receiver does not currently reside in any window. This occurs when the receiver has just been removed from its superview or when the receiver has just been added to a superview that is not attached to a window. Overrides of this method may choose to ignore such cases if they are not of interest.
弹出键盘: willMoveToWindow -> willMoveToSuperview -> didMoveToWindow -> didMoveToSuperview
return隐藏键盘: willMoveToSuperview -> willMoveToWindow -> didMoveToWindow -> didMoveToSuperview
Q: willMoveToWindwo与willMoveToSuperview两者之间有什么区别呢?
布局和子视图管理
setNeedsLayout 与 setNeedsDisplay
1) setNeedsLayout: 可让视图主动更新布局,默认调用layoutSubViews,可以处理子视图中的一些数据
2) setNeedsDisplay/ setNeedsDisplayInRect: 异步执行, 会调用drawRect,就可以拿到UIGraphicsGetCurrentContext就可以画画了
ps: 该函数为图层设置了一个标识,显示的还是原来的内容。(所以多次调用该函数并不会造成性能损失)
渲染系统准备好,图层会装配它的后备存储。 然后建立一个Core Graphics上下文(CGContextRef),将后备存储对应内存中的数据恢复出来,绘图会进入对应的内存区域,并使用 CGContextRef绘制。
CGContextref使用方法: UIKit将后备存储的CGContextRef推进graphics context stack,UIGraphicsGetCurrent()会返回对应的上下文,绘图将会进入涂层的后备存储。
layoutSubviews被调用的情况:
1) . addSubview会出发layoutSubviews,init初始化不会调用layoutSubviews;
2). 修改view的frame会出发layoutSubviews;
3). 滚动UIScrollView会出发layoutSubviews;
4). 旋转会出发父UIView的layoutSubviews事件; (?2. 子UIView的layoutSubviews事件为什么不会触发)
5). 改变UIView大小也会触发父UIView的layoutSubviews事件;
6). 调用setLayoutSubviews.
drawRect会被调用的情况:
1) 调用sizeToFit后被调用(ps: 调用sizeToFit计算出size,然后系统自动调用drawRect方法);[提倡]
2) 通过设置contentMode属性值为UIViewContentModeRedraw,则在每次设置或更改frame的时候自动调用drawRect:。[不提倡]
3) 调用setNeedsDisplay/setNeedsDisplayInRect: 会触发drawRect: ,前提是rect不为0;[不提倡]
drawRect是在loadView,viewDidLoad两方法后调用。该方法无法手动调用,只有通过调用其他方法触发.
ps : 初始化时未设置rect,则不自动调用drawRect。
小结
总结
1. 通过重写drawRect完成UIView中的绘图操作,在drawRect中获取绘图上下文(CGContextRef)。绘图后不建议通过调用drawRect方法进行绘制,而是通过调用setNeedsDisplay或者setNeedsDisplayInRect。
2. drawRect是在loadView与viewDidload之后调用
参考资料:
苹果官方文档;
UIview需要知道的一些事情:setNeedsDisplay、setNeedsLayout
谈谈UIView的几个layout方法-layoutSubviews、layoutIfNeeded、setNeedsLayout...