在mac和iOS开发中,我们都需要自定义一些公用的view,这样就可以在很多父视图中加入自定义的view,提高view的复用率。但是mac开发和iOS开发有些区别,我在mac开发公用view的时候,就遇到了一个不小的坑,现总结如下。
1、我用一个简单的demo来说明一下问题,先看下效果图:
我希望把红色的视图封装成一个公用的自定义view,可以被加载到不同的父视图中。现在我们放到windows上,通过一个按钮来改变红色view的宽度,在红色view的约束被更新的时候,我希望测试按钮可以一直保持在红色视图的居中位置。好,接下来分析代码。
2、创建一个NSView的子类,命名为SubView,同时创建一个同名的xib。
如下图所示,添加一个测试按钮,并设置居中。
3、在initWithCoder方法中,设置subView的视图大小根据在父视图中的实际大小改变。
xib自定义NSView的详细资料见链接:xib自定义NSView
- (instancetype)initWithCoder:(NSCoder*)coder
{
NSString* nibName = NSStringFromClass([self class]);
self = [super initWithCoder:coder];
if (self) {
if ([[NSBundle mainBundle] loadNibNamed:nibName
owner:self
topLevelObjects:nil]) {
[self.view setFrame:[self bounds]];
[self addSubview:self.view];
}
}
return self;
}
- (void)awakeFromNib
{
self.view.wantsLayer = YES;
self.view.layer.backgroundColor = [NSColor redColor].CGColor;
}
4、在window中加入一个NSView,并修改类名为SubView,设置自动布局居中对齐,并设置宽和高,将宽度的约束绑定到变量@property (weak) IBOutlet NSLayoutConstraint *widLayCon;
3、Windows视图左边放置一个change按钮,并绑定按钮的action事件如下:
- (IBAction)changeTheWidth:(id)sender {
self.widLayCon.constant -= 20;
}
4、点击change按钮,发现红色SubView的视图宽度改变了,但是红色视图内的测试按钮还是在原地,并没有根据父视图的改变而自动布局。
5、原因就在于,红色视图在父视图中改变的时候,并没有通知到本身最顶层的custom view改变,只要在SubView.m中加入如下代码即可:
- (void)layout
{
[super layout];
[self.view setFrame:[self bounds]];
}
6、这就是我们想要的效果图,完美。