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

闲来蛋疼,想看看每当我们以各种方式创建一个控件的时候,系统底层到底帮我们做了什么事儿!相信各位看官在开发中经常也会把系统自动调用的一些方法给拦截下来,再在这些方法中添加自己想实现的某个功能的代码。下面小小研究了某些控件创建时候系统自动帮助我们调用的某些方法。
    我们创建控件的方法有三种
     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 state
41      }
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方法。
    
    闲来蛋疼,写写博客,希望能帮助读者更深的了解到创建控件是系统会自动调用的方法。

时间: 2024-10-11 23:05:51

创建控件系统自动调用方法的小小研究的相关文章

动态创建控件 #Create(...)

1.在类中创建一个控件对象;例:CButton m_btn;2.用Create创建一个对象(#其实已经与其绑定)m_btn.Create(.....); #注意Create()函数的参数3. #这是动态创建控件的一种方法....

关于“线程间操作无效: 从不是创建控件’textBox1‘的线程访问它”异常的解决方法

线程间操作无效: 从不是创建控件“textBox1”的线程访问它 背景:通过一个辅助线程计算出的一个值赋给textBox1.text;解决办法:1.直接在窗体的构造函数中加:System.Windows.Forms.Control.CheckForIllegalCrossThreadCalls = false; 此时把所有的控件 合法性线程检查全部都给禁止掉了. 2.通过代理来解决(msdn) private delegate void SetTextCallback(string text);

线程间操作无效: 从不是创建控件“控件id”的线程访问它。(.net跨线程执行方法)

找了好久资料,终于解决了,特此记录下来. 1 delegate void DelListHandler(string number); /// <summary> /// 按标识删除listview内容 /// </summary> /// <param name="number">标识</param> private void DelListViewLog(string number) { for (int i = 0; i <

线程间操作无效:从不是创建控件的线程访问它的三种方法

访问 Windows 窗体控件本质上不是线程安全的.如果有两个或多个线程操作某一控件的状态,则可能会迫使该控件进入一种不一致的状态.还可能出现其他与线程相关的 bug,包括争用情况和死锁.确保以线程安全方式访问控件非常重要. 解决办法 1.把CheckForIllegalCrossThreadCalls设置为false 在多线程程序中,新创建的线程不能访问UI线程创建的窗口控件,如果需要访问窗口中的控件,可以在窗口构造函数中将CheckForIllegalCrossThreadCalls设置为

Android中通过WebView控件实现与JavaScript方法相互调用的地图应用

在Android中通过WebView控件,可以实现要加载的页面与Android方法相互调用,我们要实现WebView中的addJavascriptInterface方法,这样html才能调用android方法,在这里我个人觉得有点和DWR相似. 为了让大家容易理解,我写了一个简单的Demo,具体步骤如下: 第一步:新建一个Android工程,命名为WebViewDemo(这里我在assets里定义了一个html页面). 第二步:修改main.xml布局文件,增加了一个WebView控件还有But

线程间操作无效: 从不是创建控件的线程访问它的三种方法

原文:http://www.cnblogs.com/luckboy/archive/2010/12/19/1910785.html 1.把CheckForIllegalCrossThreadCalls设置为false 2.利用委托 delegate void SetTextCallBack(string text); private void SetText(string text) { if (this.txt_a.InvokeRequired) { SetTextCallBack stcb

C#后台创建控件并获取值的方法

本文实例讲述了C#后台创建控件并获取值的方法.分享给大家供大家参考.具体实现方法如下: 前台代码: 代码如下: <form id="form1″ runat="server"> <div> <div class="item"> Please input a number: <asp:TextBox runat="server" CssClass="item" ID="

026-代码创建控件-iOS笔记

学习目标 1.[理解]代码创建控件过程 2.[理解]代码实现QQ登陆界面 3.[理解]图片浏览器 4.[理解]汤姆猫小游戏 一.代码创建控件过程 所有控件都是类的对象,不同的类创建可以不同类型的控件.也是就说创建一个控件其实就是创建一个对应类的对象. 常用控件类型 UIButton:按钮,界面上可点击的大都是按钮 UILabel:标签,界面上只显示文字不能点击大都是标签 UITextField:文本框,界面上可输入数据的文本框 UIImageView:图片框,界面上不可点击的图片大都是图片框 使

iOS开发——实战技术OC篇&amp;点击状态栏ScrollView(包括子控件)自动滚到顶部

点击状态栏ScrollView(包括子控件)自动滚到顶部 其实这种方式我们平时见的还是比较多的,而且适合用户的需求,所以就搬来琢磨了一下,感觉效果还不错 这里就直接将解决思路一一写出来不将代码分段展示了,在代码中我加了详细的注释objective-c的套路和swift基本一样,在最后会将Swift和objective-c的代码一起放上,如果需要直接解决问题的童鞋可以直接将代码拷贝到工程里即可 首先创建一个topWindow继承至NSObject,这里我们考虑将这个功能完全封装起来,所以所有的方法