UIView生命周期
新建一个继承UIView的视图SView,在.m文件实现
@implementation SView
- (void)awakeFromNib
{
[super awakeFromNib];
NSLog(@"%@____________%@", @(_count++), NSStringFromSelector(_cmd));
}
- (instancetype)initWithCoder:(NSCoder*)coder
{
if(self= [superinitWithCoder:coder]) {
NSLog(@"%@____________%@", @(_count++), NSStringFromSelector(_cmd));
}
return self;
}
- (instancetype)initWithFrame:(CGRect)frame
{
if(self= [superinitWithFrame:frame]) {
NSLog(@"%@____________%@_______%@", @(_count++), NSStringFromSelector(_cmd), NSStringFromCGRect(frame));
}
return self;
}
- (instancetype)init {
self= [superinit];
if(self) {
NSLog(@"%@____________%@", @(_count++), NSStringFromSelector(_cmd));
}
return self;
}
- (void)layoutSubviews {
[super layoutSubviews];
NSLog(@"%@____________%@", @(_count++), NSStringFromSelector(_cmd));
}
- (void)didAddSubview:(UIView*)subview {
[superdidAddSubview:subview];
NSLog(@"%@____________%@________%@", @(_count++), NSStringFromSelector(_cmd), subview);
}
- (void)willRemoveSubview:(UIView*)subview {
[super willRemoveSubview:subview];
NSLog(@"%@____________%@________%@", @(_count++), NSStringFromSelector(_cmd), subview);
}
- (void)willMoveToSuperview:(nullableUIView*)newSuperview {
[superwillMoveToSuperview:newSuperview];
NSLog(@"%@____________%@________%@",@(_count++),NSStringFromSelector(_cmd), newSuperview);
}
- (void)didMoveToSuperview {
[super didMoveToSuperview];
NSLog(@"%@____________%@", @(_count++), NSStringFromSelector(_cmd));
}
- (void)willMoveToWindow:(nullableUIWindow*)newWindow {
[superwillMoveToWindow:newWindow];
NSLog(@"%@____________%@_______%@", @(_count++), NSStringFromSelector(_cmd), newWindow);
}
- (void)didMoveToWindow {
[super didMoveToWindow];
NSLog(@"%@____________%@", @(_count++), NSStringFromSelector(_cmd));
}
- (void)removeFromSuperview {
[super removeFromSuperview];
NSLog(@"%@____________%@", @(_count++), NSStringFromSelector(_cmd));
}
- (void)dealloc {
NSLog(@"%@____________%@", @(_count++), NSStringFromSelector(_cmd));
}
运行代码:
- (void)removeSview
{
NSLog(@"\n---------————————————————————销毁——————\n");
[self.sView removeFromSuperview];
self.sView=nil;
}
- (void)viewDidLoad {
[super viewDidLoad];
NSLog(@"\n---------————————————————————创建——————\n");
self.sView= [[SViewalloc]init];
[self.view addSubview:self.sView];
[self performSelector:@selector(removeSview) withObject:nil afterDelay:5];
}
运行结果:
2020-07-17 17:25:11.166846+0800 Test[21054:3473399] ---------————————————————————创建——————
0____________initWithFrame:_______{{0, 0}, {0, 0}}
1____________init
2____________willMoveToSuperview:________<UIView: 0x7fd7adc10940; frame = (0 0; 414 896); autoresize = W+H; layer = <CALayer: 0x600000af2bc0>>
3____________didMoveToSuperview
4____________willMoveToWindow:_______<UIWindow: 0x7fd7aea09830; frame = (0 0; 414 896); gestureRecognizers = <NSArray: 0x600000496d90>; layer = <UIWindowLayer: 0x600000af5400>>
5____________didMoveToWindow
6____________layoutSubviews
---------————————————————————销毁——————
7____________willMoveToSuperview:________(null)
8____________willMoveToWindow:_______(null)
9____________didMoveToWindow
10____________didMoveToSuperview
11____________removeFromSuperview
12____________dealloc
给sView添加一个子视图
[self.sView addSubview:[[UIView alloc] initWithFrame:CGRectMake(0, 0, 10, 10)]];
重新运行,运行结果:
2020-07-17 17:31:13.150901+0800 Test[21249:3477510]
---------————————————————————创建——————
0____________initWithFrame:_______{{0, 0}, {0, 0}}
1____________init
2____________didAddSubview:________<UIView: 0x7fd67340d6c0; frame = (0 0; 10 10); layer = <CALayer: 0x600003d9a640>>
3____________willMoveToSuperview:________<UIView: 0x7fd67340d960; frame = (0 0; 414 896); autoresize = W+H; layer = <CALayer: 0x600003d9a5e0>>
4____________didMoveToSuperview
5____________willMoveToWindow:_______<UIWindow: 0x7fd67420e750; frame = (0 0; 414 896); gestureRecognizers = <NSArray: 0x6000033e5d40>; layer = <UIWindowLayer: 0x600003d9c8c0>>
6____________didMoveToWindow
7____________layoutSubviews
8____________layoutSubviews
---------————————————————————销毁——————
9____________willMoveToSuperview:________(null)
10____________willMoveToWindow:_______(null)
11____________didMoveToWindow
12____________didMoveToSuperview
13____________removeFromSuperview
14____________dealloc
15____________willRemoveSubview:________<UIView: 0x7fd67340d6c0; frame = (0 0; 10 10); layer = <CALayer: 0x600003d9a640>>
1、虽然调用init初始化,但是init会先调用initWithFrame:并默认frame为CGRectZero
2、给UIView添加子视图才会调用didAddSubview:和willRemoveSubview:方法,willRemoveSubview:方法是在dealloc后面执行的。如果有多个子视图,willRemoveSubview:会循环执行,直到移除所有子视图
3、添加子视图会调用layoutSubviews
4、添加和销毁都会调用- (void)willMoveToSuperview:(nullable UIView *)newSuperview 和- (void)willMoveToWindow:(nullable UIWindow *)newWindow,可以根据参数判断,nil则为销毁,否则为创建
5、- (void)didMoveToSuperview 和- (void)didMoveToWindow,可以根据self.superview判断,nil则为销毁,否则为创建
6、removeFromSuperview、dealloc两个方法(layoutSubviews在子视图布局变动时会多次调用)只执行了一次,所以可以在这两个方法中执行释放内存等操作(移除观察者,定时器等)。
exp:
如果在initWithFrame中有view的初始化相关操作,layoutSubviews会调用两次。layoutSubviews只进行布局相关处理,不能有view初始化操作(当子视图布局改变时会调用,能多次调用),下面是layoutSubviews的触发条件:
1、init初始化不会触发layoutSubviews,但是用initWithFrame进行初始化时,当rect的值不为CGRectZero时,也会触发。
2、addSubview会触发layoutSubviews。
3、设置UIView的Frame会触发layoutSubviews,当然前提是frame的值设置前后发生了变化。
4、滚动一个UIScrollView会触发layoutSubviews。
5、旋转Screen会触发父UIView上的layoutSubviews。
6、改变一个UIView大小的时候也会触发父UIView上的layoutSubviews。
7、直接调用setLayoutSubviews。
UIView的绘制原理
当UIView调用setNeedDisplay之后,系统会调用view对应layer的 setNeedsDisplay,在当前runloop即将结束的时候调用CALayer的display方法。
CALayer的display方法的内部实现,首先会判断layer的delegete是否响应display方法,如果代理不响应就会进入到系统的绘制流程当中,如果响应,实际上就为我们提供了异步绘制的接口,这样就构成了UIView的绘制原理
系统绘制流程:
CALayer会在内部创建一个backing store(CGContextRef),我们一般在drawRect中可以通过上下文堆栈当中拿到当前栈顶的context。然后layer判断是否有代理,如果没有代理会调用layer的drawInContext方法,如果实现了代理就会调用delegete的drawLayer:inContext方法,这是在发生在系统内部当中的,然后在合适的时机给予回调方法,也就是View的drawRect方法。可以通过drawRect方法做一些其他的绘制工作。然后无论哪两个分支,都由CALayer上传backing store(最终的位图)到CPU。然后结束系统的绘制流程。
异步绘制流程:
借用系统给开的这个口子,即[layer.delegate displayLayer:]
在这个异步绘制过程中就需要代理负责生成对应的bitmap(位图)
同时设置bitmap作为layer.contents属性的值
网友评论