一、介绍

前面介绍了VC的生命周期,闲着没事也来捋一捋View的生命周期,简单用两个类型的View来监测。一个View纯代码创建,另一个View使用Xib创建。

iOS:捋一遍View的生命周期-LMLPHP

二 、代码

MyCodeView: 

//
// MyCodeView.m
// 生命周期
//
// Created by 夏远全 on 2019/11/3.
// Copyright © 2019 Beijing Huayue Education Technology Co., Ltd. All rights reserved.
// #import "MyCodeView.h" @implementation MyCodeView - (instancetype)initWithFrame:(CGRect)frame {
NSLog(@"myCodeView-------%s",__func__);
return [super initWithFrame:frame];
} - (nullable instancetype)initWithCoder:(NSCoder *)coder {
NSLog(@"myCodeView-------%s",__func__);
return [super initWithCoder:coder];
} -(void)awakeFromNib {
NSLog(@"myCodeView-------%s",__func__);
return [super awakeFromNib];
} -(instancetype)init {
NSLog(@"myCodeView-------%s",__func__);
return [super init];
} - (void)willMoveToSuperview:(nullable UIView *)newSuperview {
NSLog(@"myCodeView-------%s",__func__);
[super willMoveToSuperview:newSuperview];
} - (void)didMoveToSuperview {
NSLog(@"myCodeView-------%s",__func__);
[super didMoveToSuperview];
} - (void)willMoveToWindow:(nullable UIWindow *)newWindow {
NSLog(@"myCodeView-------%s",__func__);
[super willMoveToWindow:newWindow];
} - (void)didMoveToWindow {
NSLog(@"myCodeView-------%s",__func__);
[super didMoveToWindow];
} - (void)layoutSubviews {
NSLog(@"myCodeView-------%s",__func__);
[super layoutSubviews];
} - (void)drawRect:(CGRect)rect {
NSLog(@"myCodeView-------%s",__func__);
[super drawRect:rect];
} -(void)dealloc {
NSLog(@"myCodeView-------%s",__func__);
} @end

MyXibView: 

//
// MyXibView.m
// 生命周期
//
// Created by 夏远全 on 2019/11/3.
// #import "MyXibView.h" @implementation MyXibView - (instancetype)initWithFrame:(CGRect)frame {
NSLog(@"myXibView-------%s",__func__);
return [super initWithFrame:frame];
} - (nullable instancetype)initWithCoder:(NSCoder *)coder {
NSLog(@"myXibView-------%s",__func__);
return [super initWithCoder:coder];
} -(void)awakeFromNib {
NSLog(@"myXibView-------%s",__func__);
return [super awakeFromNib];
} -(instancetype)init {
NSLog(@"myXibView-------%s",__func__);
return [super init];
} - (void)willMoveToSuperview:(nullable UIView *)newSuperview {
NSLog(@"myXibView-------%s",__func__);
[super willMoveToSuperview:newSuperview];
} - (void)didMoveToSuperview {
NSLog(@"myXibView-------%s",__func__);
[super didMoveToSuperview];
} - (void)willMoveToWindow:(nullable UIWindow *)newWindow {
NSLog(@"myXibView-------%s",__func__);
[super willMoveToWindow:newWindow];
} - (void)didMoveToWindow {
NSLog(@"myXibView-------%s",__func__);
[super didMoveToWindow];
} - (void)layoutSubviews {
NSLog(@"myXibView-------%s",__func__);
[super layoutSubviews];
} - (void)drawRect:(CGRect)rect {
NSLog(@"myXibView-------%s",__func__);
[super drawRect:rect];
} -(void)dealloc {
NSLog(@"myCodeView-------%s",__func__);
} @end

三 、注释

 init: 通过init实例化时调用,最终会调用initWithFrame,默认使用frame为CGRectZero

 initWithFrame: 给出一个frame进行实例化时,会调用

 initWithCoder: 通过xib文件创建时,进行反序列化调用

 awakeFromNib: 通过xib反序列化后唤醒,初始化调用

 willMoveToSuperview: 在视图即将加入或者移除时调用,如果参数newSuperview有值,则为即将加入到父视图,如果为空值,则即将从父视图移除

 didMoveToSuperview: 在视图即完全加入或者移除时调用,如果参数newSuperview有值,则为完全加入到父视图,如果为空值,则完全从父视图移除

 willMoveToWindow: 在视图即将加入或者移除时调用,如果参数newWindow有值,则为即将加入到窗体,如果为空值,则即将从窗体移除

 didMoveToWindow: 在视图完全加入或者移除时调用,如果参数newWindow有值,则为完全加入到窗体,如果为空值,则完全从窗体移除

 layoutSubviews: 对所有的子视图进行布局时调用

 drawRect: 通过xib文件创建的view在结束布局后进行绘制,此时调用

 dealloc: 当前视图从父视图移除并置为空时,对象销毁调用

四 、测试

MyCodeView:

- (void)viewDidLoad {
[super viewDidLoad];
NSLog(@"创建过程:");
_codeView = [[MyCodeView alloc] init];
[self.view addSubview:_codeView];
} -(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
NSLog(@"移除过程:");
[self.codeView removeFromSuperview];
[self setCodeView:nil];
}
-- ::48.017455+ 生命周期[:] 创建过程:
-- ::48.017693+ 生命周期[:] myCodeView--------[MyCodeView init]
-- ::48.017831+ 生命周期[:] myCodeView--------[MyCodeView initWithFrame:]
-- ::48.018089+ 生命周期[:] myCodeView--------[MyCodeView willMoveToSuperview:]
-- ::48.018259+ 生命周期[:] myCodeView--------[MyCodeView didMoveToSuperview]
-- ::48.030801+ 生命周期[:] myCodeView--------[MyCodeView willMoveToWindow:]
-- ::48.031085+ 生命周期[:] myCodeView--------[MyCodeView didMoveToWindow]
-- ::48.035874+ 生命周期[:] myCodeView--------[MyCodeView layoutSubviews]
-- ::49.043080+ 生命周期[:] 移除过程:
-- ::49.043505+ 生命周期[:] myCodeView--------[MyCodeView willMoveToSuperview:]
-- ::49.043670+ 生命周期[:] myCodeView--------[MyCodeView willMoveToWindow:]
-- ::49.043856+ 生命周期[:] myCodeView--------[MyCodeView didMoveToWindow]
-- ::49.043977+ 生命周期[:] myCodeView--------[MyCodeView didMoveToSuperview]
-- ::49.044246+ 生命周期[:] myCodeView--------[MyCodeView dealloc]

MyXibView:

- (void)viewDidLoad {
[super viewDidLoad]; NSLog(@"创建过程:");
_xibView = [[NSBundle mainBundle] loadNibNamed:@"MyXibView" owner:self options:nil][];
[self.view addSubview:_xibView];
} -(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
NSLog(@"移除过程:");
[self.xibView removeFromSuperview];
[self setXibView:nil];
}
-- ::37.271733+ 生命周期[:] 创建过程:
-- ::37.272366+ 生命周期[:] myXibView--------[MyXibView initWithCoder:]
-- ::37.272802+ 生命周期[:] myXibView--------[MyXibView awakeFromNib]
-- ::37.273005+ 生命周期[:] myXibView--------[MyXibView willMoveToSuperview:]
-- ::37.273185+ 生命周期[:] myXibView--------[MyXibView didMoveToSuperview]
-- ::37.285532+ 生命周期[:] myXibView--------[MyXibView willMoveToWindow:]
-- ::37.285846+ 生命周期[:] myXibView--------[MyXibView didMoveToWindow]
-- ::37.291993+ 生命周期[:] myXibView--------[MyXibView layoutSubviews]
-- ::37.292182+ 生命周期[:] myXibView--------[MyXibView layoutSubviews]
-- ::37.292659+ 生命周期[:] myXibView--------[MyXibView drawRect:]
-- ::38.979328+ 生命周期[:] 移除过程:
-- ::38.979581+ 生命周期[:] myXibView--------[MyXibView willMoveToSuperview:]
-- ::38.979720+ 生命周期[:] myXibView--------[MyXibView willMoveToWindow:]
-- ::38.979915+ 生命周期[:] myXibView--------[MyXibView didMoveToWindow]
-- ::38.980028+ 生命周期[:] myXibView--------[MyXibView didMoveToSuperview]
-- ::38.980257+ 生命周期[:] myCodeView--------[MyXibView dealloc]

五 、总结

  • 不论是纯代码的创建View还是xib创建的View,在添加到容器中和从容器中移除时,都会调用willMoveToSuperview、didMoveToSuperview、willMoveToWindow、didMoveToWindow这四个方法,只不过调用顺序有所变化;
  • 使用纯代码创建View时,只要调用了init方法,就一定会调用initWithFrame方法,会调用一次布局;
  • 使用Xib创建的View时,需要进行反序列化和唤醒,也即调用initWithCoder、awakeFromNib方法, 会调用两次布局,然后进行绘制;
05-11 22:37