前言
關(guān)于 initWithNibName 和 loadNibNamed 的區(qū)別和聯(lián)系
參考:關(guān)于 initWithNibName 和 loadNibNamed 的區(qū)別和聯(lián)系
如果執(zhí)行
NSArray *views = [[NSBundle mainBundle] loadNibNamed:@"RemarkView" owner:self options:nil];
語句,發(fā)現(xiàn)崩潰届巩,請檢查對應(yīng)的.xib文件中的控件關(guān)聯(lián)是否正確硅瞧。比如如果控件類型錯了等就會導致此句崩潰。
嵌套使用xib
參考:Nested Xib Views - 使用XIB實現(xiàn)嵌套自定義視圖
有一個復雜的視圖viewA恕汇,上面有很多的subview腕唧,我們?yōu)榱烁咏怦睿瑢iewA的某部分子視圖瘾英,又獨立成一個viewB枣接。
現(xiàn)在的問題是,你的viewB已經(jīng)是用xib來生成的了方咆。那么
當你viewA也是使用xib時候月腋,你會發(fā)現(xiàn)即使你做了該做的在A.xib中添加一個UIView蟀架,然后將這個view的定制類從UIView改為類B瓣赂。發(fā)現(xiàn)B壓根沒顯示出來榆骚。這是什么情況呢?
父視圖superView添加子視圖subView的兩種方法
方法①:[self.view addSubView:view1];
方法②:xib上添加subView
subView的創(chuàng)建的兩種方式:
1煌集、代碼生成妓肢,
CustomView1 *view1 = [[CustomView1 alloc] init];
view1.titleLabel = [[UILabel alloc] init....
view1.imageView = [[UIImage alloc] init..
....
2、xib生成
xib生成也有幾種方法
①一個類只有一種xib苫纤,通過設(shè)置File's Owner將其設(shè)為某個類的所有者碉钠,同時進行關(guān)聯(lián)
這種xib方式創(chuàng)建的view,提取CustomView 的 xib 中的內(nèi)容的方法為:
UINib *nib = [UINib nibWithNibName:NSStringFromClass([self class]) bundle:nil];
NSArray *views = [nib instantiateWithOwner:self options:nil];
UIView *containerView = [views objectAtIndex:0];
如果CustomView.m(如OrderPriceInfoView1.m)未做任何處理卷拘,則其他需要添加CustomView的view上的寫法應(yīng)為如下:
- (instancetype)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
[self commonInit];
}
return self;
}
- (void)commonInit {
UINib *nib1 = [UINib nibWithNibName:NSStringFromClass([OrderPriceInfoView1 class]) bundle:nil];
NSArray *views1 = [nib1 instantiateWithOwner:self options:nil];
OrderPriceInfoView1 *orderPriceInfoView1 = [views1 objectAtIndex:0];
orderPriceInfoView1.frame = self.bounds;
[self addSubview:orderPriceInfoView1];
self.orderPriceInfoView1 = orderPriceInfoView1;
UINib *nib2 = [UINib nibWithNibName:NSStringFromClass([OrderPriceInfoView2 class]) bundle:nil];
NSArray *views2 = [nib2 instantiateWithOwner:self options:nil];
OrderPriceInfoView2 *orderPriceInfoView2 = [views2 objectAtIndex:0];
orderPriceInfoView2.frame = self.bounds;
[self addSubview:orderPriceInfoView2];
self.orderPriceInfoView2 = orderPriceInfoView2;
UINib *nib3 = [UINib nibWithNibName:NSStringFromClass([OrderPriceInfoView3 class]) bundle:nil];
NSArray *views3 = [nib3 instantiateWithOwner:self options:nil];
OrderPriceInfoView3 *orderPriceInfoView3 = [views3 objectAtIndex:0];
orderPriceInfoView3.frame = self.bounds;
[self addSubview:orderPriceInfoView3];
self.orderPriceInfoView3 = orderPriceInfoView3;
}
而我們這里為了不頻繁的在每個需要使用到這個CustomView的時候喊废,都要寫一遍這個xib中的內(nèi)容加載代碼,所以我們選擇將這個xib中的內(nèi)容加載代碼寫到CustomView初始化方法中栗弟。
例如:
//CustomXibView.m
- (instancetype)init {
self = [super init];
if (self) {
[self commonInit];
}
return self;
}
- (instancetype)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
[self commonInit];
}
return self;
}
- (instancetype)initWithCoder:(NSCoder *)aDecoder {
self = [super initWithCoder:aDecoder];
if (self) {
[self commonInit];
}
return self;
}
- (void)commonInit {
UINib *nib = [UINib nibWithNibName:NSStringFromClass([self class]) bundle:nil];
NSArray *views = [nib instantiateWithOwner:self options:nil];
UIView *containerView = [views objectAtIndex:0];
[self addSubview:containerView];
//CGRect newFrame = CGRectMake(0, 0, self.frame.size.width, self.frame.size.height);
//containerView.frame = newFrame;
[containerView mas_makeConstraints:^(MASConstraintMaker *make) {
make.edges.mas_equalTo(self);
}];
}
這樣操作后污筷,就不用再每次需要使用到CustomView的時候,都需要重復寫一遍xib中內(nèi)容的加載代碼了乍赫。
也因此瓣蛀,這樣改后,上面的代碼可改成如下
- (instancetype)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
[self commonInit];
}
return self;
}
- (void)commonInit {
OrderPriceInfoView1 *orderPriceInfoView1 = [[OrderPriceInfoView1 alloc] init];
orderPriceInfoView1.frame = self.bounds;
[self addSubview:orderPriceInfoView1];
self.orderPriceInfoView1 = orderPriceInfoView1;
OrderPriceInfoView2 *orderPriceInfoView2 = [[OrderPriceInfoView2 alloc] init];
orderPriceInfoView2.frame = self.bounds;
[self addSubview:orderPriceInfoView2];
self.orderPriceInfoView2 = orderPriceInfoView2;
OrderPriceInfoView3 *orderPriceInfoView3 = [[OrderPriceInfoView3 alloc] init];
orderPriceInfoView3.frame = self.bounds;
[self addSubview:orderPriceInfoView3];
self.orderPriceInfoView3 = orderPriceInfoView3;
}
但其實這個更方便的地方是雷厂,當你的這個CustomView是通過xib嵌套到其他xib中的時候惋增,只需要拖動一個view上去改鲫,并將該view的類設(shè)置好就可以啦。
②一個類可能有多種xib,
試想如果你的viewA是使用代碼的話呢纫塌,你是不是會在創(chuàng)建A類子視圖的時候讲弄,把B通過[NSBundle mainBundle] loadNib...]的方法寫進去。
所以這里的問題怎披,也是一樣瓶摆,針對我們將一個xib文件作為subview放入另一個xib中的話,作為subview的這個xib并不會自動被系統(tǒng)載入內(nèi)存状飞,這就出現(xiàn)了上面例子中的看不到B.xib。所以我們需要手動載入B.xib酵使。具體的做法是在類A的initWithCoder:(NSCoder)方法中使用
//正確做法
UINib *nib1 = [UINib nibWithNibName:NSStringFromClass([OrderPriceInfoView1 class]) bundle:nil];
NSArray *views1 = [nib1 instantiateWithOwner:self options:nil];
self.view1 = [views1 objectAtIndex:0];
而不是(會導致崩潰原因不詳)
//錯誤做法
NSArray *views1 = [[NSBundle mainBundle] loadNibNamed:[self class] owner:nil options:nil];
self.view1 = [views1 objectAtIndex:0];
方法手動載入B.xib即可口渔,然后將其作為subview添加到當前view中穿撮。
eg:
使用IB自定義了一個View,然后又在其他的xib文件中使用了這個View