[[NSBundle mainBundle] loadNibNamed:@"ImageTitleButton" owner:self options:nil];方式从xib加载内容视图。但是,由于布局有4种方式可选,因此不能在xib中添加约束。所以还是采用masonry进行布局(复用纯代码中的布局代码)。结果问题来了,图片的显示是正常的,但是label的约束死活不起效果,总是显示为xib中拖放的位置和大小。几经周折,最后无奈接受了一点:在xib中创建视图,而在代码中为其添加约束,这种方法不可取,经常会出现各种莫名其妙的问题(笔者之前已经因为这种做法导致的各种视图不显示、显示不正常,已经浪费了很多时间。。。)。
如果xcode输出以下错误信息,而代码添加的约束确实不存在冲突等问题,那有可能就是用代码为xib中的视图创建约束导致的。
最后,纠结好久没法解决后,就尝试换了一种思路。一开始,想在initWithCoder方法中转调initWithFrame,即如下所示:
- (instancetype)initWithCoder:(NSCoder *)aDecoder {
[self initWithFrame:CGRectZero];
return self;
}
结果发现不行,又换成如下方式:
- (instancetype)initWithCoder:(NSCoder *)aDecoder {
if (self = [super initWithCoder:aDecoder]) {
[self addSubviews];
}
return self;
}
其中addSubviews是代码中创建UIImageView和UILabel的函数:
- (void)addSubviews {
_imageView = [[UIImageView alloc] init];
[self addSubview:_imageView];
_titleLabel = [[UILabel alloc] init];
[self addSubview:_titleLabel];
}
autolayout还是之前的masonry代码,这次终于成功了。总结一下,一定不要用用代码为xib中的视图创建约束。如果是界面里添加的视图,就在界面上使用autolayout;如果像本文这样不是布局不是静态的,而是比较灵活、运行时才能确定、且区别较大、必须用代码写约束的,那就在代码中创建视图。这并不影响最后整体的自定义控件从界面创建,因为可以参照上述initWithCoder方法,将界面创建转化为纯代码方式。