你的位置:首页 > 操作系统

[操作系统]创建控件系统自动调用方法的小小研究


    闲来蛋疼,想看看每当我们以各种方式创建一个控件的时候,系统底层到底帮我们做了什么事儿!相信各位看官在开发中经常也会把系统自动调用的一些方法给拦截下来,再在这些方法中添加自己想实现的某个功能的代码。下面小小研究了某些控件创建时候系统自动帮助我们调用的某些方法。
    我们创建控件的方法有三种
     1.纯代码
     2.storyboard
     3.xib
    
    创建控件的过程中系统会自动调用底层的一些方法,方法常见的大概如下
     init
     initWithFrame
     initWithStyle
     initWithCoder
     awakeFromNib
    
    为了研究控件创建的时候,我们自定义一个testView类,其继承于UIView,获取UIView中所有的方法和属性,将其中init、initWithFrame、initWithCoder、awakeFromNib拦截并且加入打印本方法名的代码,代码如下

 1   #import "testView.h" 2  3   @implementation testView 4  5   -(instancetype)init{ 6   if (self = [super init]) { 7   NSLog(@"%s",__func__); 8    } 9   return self;10    }11 12   -(instancetype)initWithCoder:(NSCoder *)aDecoder{13   if (self = [super initWithCoder:aDecoder]) {14   NSLog(@"%s",__func__);15    }16   return self;17    }18 19   -(instancetype)initWithFrame:(CGRect)frame{20   if (self = [super initWithFrame:frame]) {21   NSLog(@"%s",__func__);22    }23   return self;24    }25 26   -(void)awakeFromNib{27   NSLog(@"%s",__func__);28    }29 30   @end

一、在控制器中通过纯代码的方式创建自定义的testView观察其底层调用的方法
    代码:
     testView * test = [[testView alloc] init];
    
    控制台打印输出:
     2015-12-31 13:49:42.514测试代码[901:157862] -[testView initWithFrame:]
     2015-12-31 13:49:42.514测试代码[901:157862] -[testView init]
    
    结论一:通过纯代码的方式创建空间会自动调用initWithFrame方法
    
    二、通过xib的方式创建
    
    代码:
         testView * test = [[[NSBundle mainBundle] loadNibNamed:@"test" owner:nil options:nil] firstObject];
    控制台打印输出:
     2015-12-31 13:59:00.724测试代码[992:192250] -[testView initWithCoder:]
     2015-12-31 13:59:00.724测试代码[992:192250] -[testView awakeFromNib]
    
    结论二:通过xib的方式创建控件,系统会自动调用initWithCoder和awakeFromNib方法
    
    三、创建UITableViewCell,多了一种initWithStyle的方法,再看看创建UITableViewCell时系统会帮我们做什么事儿叻?
    还是一样先自定义一个testCell类继承于UITableViewCell
     testCell代码:

 1   #import "testCell.h" 2  3   @implementation testCell 4  5   -(instancetype)init{ 6   if (self = [super init]) { 7   NSLog(@"%s",__func__); 8    } 9   return self;10    }11 12   -(instancetype)initWithCoder:(NSCoder *)aDecoder{13   if (self = [super initWithCoder:aDecoder]) {14   NSLog(@"%s",__func__);15    }16   return self;17    }18 19   -(instancetype)initWithFrame:(CGRect)frame{20   if (self = [super initWithFrame:frame]) {21   NSLog(@"%s",__func__);22    }23   return self;24    }25 26   -(instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier{27   if (self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]) {28   NSLog(@"%s",__func__);29    }30   return self;31    }32 33   -(void)awakeFromNib{34   NSLog(@"%s",__func__);35    }36 37   - (void)setSelected:(BOOL)selected animated:(BOOL)animated {38    [super setSelected:selected animated:animated];39 40   // Configure the view for the selected state41    }42 43   @end

一个一个来研究,先看init创建
    代码:
     testCell * cell = [[testCell alloc] init];
    
    控制台:
     2015-12-31 14:11:31.180测试代码[1030:236258] -[testCell initWithStyle:reuseIdentifier:]
     2015-12-31 14:11:31.181测试代码[1030:236258] -[testCell initWithFrame:]
     2015-12-31 14:11:31.181测试代码[1030:236258] -[testCell init]
    
    结论三:创建一个tableViewCell的时候系统底层会自动调用initWithStyle:reuseIdentifier方法和initWithFrame方法,并且是先调用initWithStyle方法,再调用initWithFrame,从正常思考的逻辑上来讲可以这么想,先确定style,再给其赋值frame。
    
    再看看通过xib创建自定义cell
    代码:
         testCell * cell = [[[NSBundle mainBundle] loadNibNamed:@"testCell" owner:nil options:nil] firstObject];
    控制台:
     2015-12-31 15:34:04.042测试代码[1264:393941] -[testCell initWithCoder:]
     2015-12-31 15:34:04.042测试代码[1264:393941] -[testCell awakeFromNib]
    
    结论四:通过xib创建cell不会调用initWithStyle:reuseIdentifier方法,因为xib里面已经定义好了cell的style,逻辑上可以这么理解。同样也先自动调用了initWithCoder,再调用awakeFromNib方法。
    
    闲来蛋疼,写写博客,希望能帮助读者更深的了解到创建控件是系统会自动调用的方法。