关于从xib加载视图
来源:互联网 发布:淘宝网怎么找店主 编辑:程序博客网 时间:2024/06/05 09:50
作者:Love@YR
链接:http://blog.csdn.net/jingqiu880905/article/details/51745617
请尊重原创,谢谢
经常会看到initWithNibName,initWithCoder,awakeFromNib,loadNibNamed 这些方法,各种头大,网上资料不少,能说清楚的不多,于是今天写了个demo来测试下这些方法何时调用。
首先,我们从视觉上区分一下loadNibName和initWithNibName。
initWithNibName 是由UIViewController及其子类调用
如:
AViewController *avc = [[AViewController alloc]initWithNibName:@"AViewController" bundle:nil];
而loadNibName则是这样:
NSArray *objectsInNib = [[NSBundle mainBundle] loadNibNamed:@"BView" owner:nil options:nil]; for(id item in objectsInNib){if([item isKindOfClass:[yourview class]]){//找到了你需要的对象,do what you want}
在这个时候生成后会让引用计数器变为1,但是需要注意得owner:self ,在owner自己dealloc得时候,系统会自动帮你将你得youview得引用计数器-1。
在xib里,第一种(一般我们创建 viewcontroller时勾选了nib生成的)
通常是这样的:
注意这里的file’s owner是你的view controller类
底下这个view就是这个view controller的根view
第二种通常是这样的:
注意看,这里的file’s owner是NSObject
这里我拖了3个控件,其中view这个所属的类名为BView,同样其它控件我也需要给它创建类并连接。
默认uiview占满屏,改下其size为freeform即可改变其大小。
一般来说我们调用loadNibNamed的到的数组即这个xib上的所有控件,我们是想要拿一些控件如view,cell等而不是viewcontroller。(这也是最常用的用途)
但是,这里我们同样可以拖入viewcontroller, navigationcontroller等任意对象。
如图:
那么这里我们得到的数组里就能有viewcontroller这个对象了。
那么同样两种创建viewcontroller的方法,分别调用了什么呢?
测试结果显示用initWithNibName方法,会调用此CustomViewController的initWithNibName,viewDidLoad
而用loadNibNamed时,执行到此句时,就会调用此数组里所有对象的initWithCoder,awakeFromNib方法。
比如我在一个xib里加入了一个view,两个view controller。执行的log显示当调用loadNibNamed时打印了:
BView——-initWithCoder———-called
AVC——-initWithCoder———-called
bVC——-initWithCoder———-called
BView——-awakeFromNib———-called
AVC——-awakeFromNib———-called
bVC——-awakeFromNib———-called
然后我拿出aVC对象,present,并没有执行AVC的viewDidLoad。
这个问题 http://www.cnblogs.com/iOS-mt/p/4362335.html 这篇文章也说了,后续再研究。
这下清晰多了。
然后 http://blog.csdn.net/richard_rufeng/article/details/26508977 这篇文章说initWithNibName方法是延迟加载 loadNibNamed方法是即时加载,具体原理先不管了。就这样。
——————————我是分割线———————————————-
上面说了loadNibNamed方法一般用来加载控件对象的。下面我们来看用此方法生成一个CustomView对象和直接alloc一个此对象调用的方法有何区别:
在某个controller里我创建了avc并present
AViewController *avc = [[AViewController alloc] init]; [self presentViewController:avc animated:YES completion:nil];
在AViewController的viewDidLoad里:
NSArray *bvarr = [[NSBundle mainBundle] loadNibNamed:@"BView" owner:nil options:nil]; BView *bv = [bvarr objectAtIndex:0];// [bv setFrame: CGRectMake(10, 10, 100, 100)];//此句话无效 [self.view addSubview:bv];
这里BView.xib里只有一个UIView的子类BView。和上面AVC一样,loadNibNamed时会依次调用BView的initWithCoder,awakeFromNib。还有view controller所没有的layoutSubviews。
然后测试发现
1. 对于bview的子控件,都得在awakeFromNib或者layoutSubviews里设置其属性才能生效,在initWithCoder是不行的。这篇文章也说了。
2. self.frame必须在layoutSubviews里设置才能生效!!
3. initWithCoder,awakeFromNib里设置显示的效果都不准确。网上有人说是因为还没加载完。且如上段代码所注释,直接[bv setFrame: CGRectMake(10, 10, 100, 100)]也没有用。
代码:
BView.m
- (id)initWithCoder:(NSCoder *)aDecoder{ self = [super initWithCoder:aDecoder]; if (self) { NSLog(@"BView-------initWithCoder----------called"); } return self;}-(void)awakeFromNib{ NSLog(@"BView-------awakeFromNib----------called"); self.bviewLabel.text = @"b商品"; self.bviewLabel.backgroundColor = [UIColor purpleColor]; self.bviewLabel.frame = CGRectMake(5, 10, 50, 30);//当不用autolayout的时候代码设置self.bviewLabel.frame是生效的 self.backgroundColor = [UIColor greenColor];// self.frame = CGRectMake(10, 10, 300, 200);}-(void)layoutSubviews{ NSLog(@"BView-------layoutSubviews----------called"); self.frame = CGRectMake(10, 10, 300, 200);//此句必须写这个方法里}
——————————我是分割线———————————————-
下面看看直接alloc生成此view对象会调用哪些方法:
当不在外设置view的frame时,也不在initWithFrame,init里设置frame时:
CView *cv = [[CView alloc]init]; [self.view addSubview:cv];
打印显示先后走了initWithFrame,init方法
当在initWithFrame或者init里或者外部cv setFrame时,会触发layoutSubviews。
打印显示先后走了initWithFrame,init,layoutSubviews方法
init里的setFrame会覆盖initWithFrame里的,layoutSubviews里如果写了setFrame则会覆盖init里的。
-(instancetype)initWithFrame:(CGRect)frame{ if (self = [super initWithFrame:frame]) { NSLog(@"CView-------initWithFrame----------called"); self.frame = CGRectMake(0, 0, 40, 40); self.backgroundColor = [UIColor greenColor]; UILabel * clableview = [[UILabel alloc]initWithFrame:CGRectMake(0, 0, 10, 10)]; clableview.text = @"c商品"; clableview.backgroundColor = [UIColor purpleColor]; [self addSubview:clableview]; } return self;}- (instancetype)init{ if (self = [super init]) { NSLog(@"CView-------init----------called"); // self.frame = CGRectMake(10, 10, 20, 80); } return self;}-(void)layoutSubviews{ NSLog(@"CView-------layoutSubviews----------called"); // self.frame = CGRectMake(10, 10, 80, 20);}
当使用 CView *cv = [[CView alloc]initWithFrame:CGRectMake(10, 10, 10, 10)];
会调用initWithFrame和layoutSubviews不会调用init方法。
所以可以直接在initWithFrame里面去设置frame backgroundcolor subview等。
- 关于从xib加载视图
- 从XIB加载视图异常
- iOS在Xib加载自定义Xib视图
- 加载xib到视图上
- 关于xib的加载
- 从Xib文件加载UIView
- 关于iOS xib加载实践
- 从一个xib文件中加载另一个xib文件
- 控件从xib加载,默认尺寸跟xib一样大
- ios-使用Xib加载或Storyboard加载控制器(视图)
- iOS:从xib文件中加载Cell
- 从XIB、Storyboard加载View或ViewController
- 重用从xib加载的UITableViewCell
- 从xib加载UIViewController的一个坑
- xib创建的空视图 加载的时候 设置大小
- 从storyboard加载视图控制器
- iOS开发之xib 加载xib视图需要用到的方法
- Swift中tableView加载通过xib创建的headerView时,无法显示xib视图内容.
- Hadoop安装教程及单机/伪分布式配置
- Objective-C中block用法
- SAP调用WSDL报错,求解!
- 编写高效jQuery代码
- VMware 下USB 识别问题的解决办法!!!
- 关于从xib加载视图
- 写在各种题解之前的话
- 浅析Java中的final关键字
- C#中正则表达式的使用
- ROS:Nvidia Jetson TK1平台安装使用ROS
- hdu-3480-Division-dp-斜率优化
- setRotation
- 使用REFERER跳转回修改前的分页页面
- 去掉字符串String中的换行或空格