轉(zhuǎn)自:http://www.lxweimin.com/p/68b383b129f9
1.要重寫UIView的initWithFrame:方法而不是init方法
為什么呢?因?yàn)楫?dāng)外部調(diào)用init的方法的時(shí)候,其內(nèi)部也會(huì)默默地調(diào)用initWithFrame:方法,你不能保證別的同事在調(diào)用你的類的時(shí)候不會(huì)直接調(diào)用initWithFrame:方法,這時(shí)如果你僅重寫了init方法,那么兩個(gè)子控件便無(wú)從創(chuàng)建.
于是我們寫成這樣:
- (instancetype)initWithFrame:(CGRect)frame {
if (self = [super initWithFrame:frame]) {
/* 添加子控件的代碼*/
}
return self;
}
2.不要在構(gòu)造方法里面直接取自身(self,或者說(shuō)本視圖)的寬高,這時(shí)候取到的寬高是不準(zhǔn)的.
我想初學(xué)自定義tableViewCell的小伙伴都遇到過(guò)類似這樣的問(wèn)題:
重寫cell的初始化方法向cell內(nèi)添加子控件時(shí)
(假設(shè)cell的高度設(shè)為100,想要添加一個(gè)label在cell的底部),
于是這樣寫:
label.frame = CGRectMake(0,self.frame.size.height - 20, 100, 20),
運(yùn)行出來(lái)卻發(fā)現(xiàn)添加的label并不在我們期望的位置(底部),
而是在cell比較偏上的位置(實(shí)際y的值是44-20而不是100-20).
然后在debug的時(shí)候發(fā)現(xiàn):雖然cell的高度已經(jīng)設(shè)定成為100,但在初始化方法里面取到的cell的高度仍然是默認(rèn)的44.
這其實(shí)也是剛才說(shuō)的原因?qū)е碌?我們不能在控件的構(gòu)造方法里面取其frame或者bounds,這時(shí)候取值是不準(zhǔn)確的.
所以在重新構(gòu)造方法的時(shí)候,我們只需要把控件放進(jìn)去,暫時(shí)先不用考慮他們?cè)谑裁次恢?
-
(instancetype)initWithFrame:(CGRect)frame {
if (self = [super initWithFrame:frame]) {
self.imageView = [[UIImageView alloc]init];
[self addSubview:self.imageView];self.label = [[UILabel alloc]init]; self.label.textAlignment = NSTextAlignmentCenter; [self addSubview:self.label];
}
return self;
}
3.在layoutSubViews方法里面布局子控件
如下:
-
(void)layoutSubviews {
// 一定要調(diào)用super的方法
[super layoutSubviews];// 確定子控件的frame(這里得到的self的frame/bounds才是準(zhǔn)確的)
CGFloat width = self.bounds.size.width;
CGFloat height = self.bounds.size.height;
self.imageView.frame = CGRectMake(0, 0, width, width);
self.label.frame = CGRectMake(0, width, width, height - width);
}
這里要注意的就是需要在布局之前一定要先調(diào)用父類的layoutSubviews方法.
由于在這個(gè)方法里可以獲取MyView準(zhǔn)確的寬和高,我們直接取它的寬高來(lái)設(shè)置imageView和label的寬高就可以
當(dāng)然,子控件的創(chuàng)建不一定要寫在MyView的構(gòu)造方法里面,既然聲明成為屬性,使用懶加載(重寫屬性的get方法)也是一個(gè)不錯(cuò)的選擇.