假设我有一个XIB文件(MyView. XIB)包含一个单一的根UIView,它的类是一些自定义UIView子类(MyView)。
我想从XIB文件创建MyView的实例(在代码中),但我也希望文件的所有者是MyView本身的实例(这样我就可以从XIB链接IBOutlets到代码)。
换句话说,MyView是XIB中根视图的类,它也被设置为文件的所有者类。
我在MyView实现中尝试了这样的东西:
- (id)initFromNib {
self = [[[NSBundle mainBundle] loadNibNamed:@"MyView" owner:self options:nil] firstObject];
return self;
}
然后我意识到这是没有意义的,因为在那一点self
是nil,所以文件的所有者被设置为nil(不好)。
这开始感觉像一个先有鸡还是先有蛋的问题,因为我需要文件的所有者是即将创建的实例,在它被创建之前。
然后我尝试这样做:
- (id)initWithFrame:(CGRect)frame {
self = [super initWithFrame:CGRectMake(0.0, 0.0, 310, 166)];
if (self) {
self = [[[NSBundle mainBundle] loadNibNamed:@"MyView" owner:self options:nil] firstObject];
}
return self;
}
显然这是一个临时的黑客只是看看它是否会工作,但不去。视图被加载并正确显示,但当我按下其中一个按钮(它有关联的IBActions)时,应用程序崩溃了。
我错过了什么明显的吗?还是我的理解有缺陷?
一般的问题是,我只是想有一个自定义的UIView子类与关联的XIB,其中包含该视图的可视化表示,我还希望能够关联iboutlet之间的XIB和它相应的UIView子类。
欢迎大家提出建议
经过一番挖掘,我找到了一个解决方法。基本上,我没有将IBOutlets和IBActions链接到文件的所有者,而是将它们直接链接到根视图的类(该类通过自定义子类公开了ib属性)。
关键是不依赖于文件的所有者,而是直接将出口和操作连接到自定义视图。
这是我最后使用的初始化式:
- (instancetype)initFromNib {
return [[[NSBundle mainBundle] loadNibNamed:@"MyView" owner:nil options:nil] firstObject];
}
现在似乎工作得很好。
我已经在UIView上创建了一个类别,用于从XIB初始化视图(它假设XIB名称与类名称相同)。
UIView + Initialization.h
#import <UIKit/UIKit.h>
@interface UIView (Initialization)
- (instancetype)initFromNib;
@end
UIView + Initialization.m
#import "UIView+Initialization.h"
@implementation UIView (Initialization)
- (instancetype)initFromNib {
return [[[NSBundle mainBundle] loadNibNamed:NSStringFromClass(self.class) owner:nil options:nil] firstObject];
}
@end
你可以简单地做:
MyView *myView = [[MyView alloc] initFromNib];
假设你有一个MyView.xib
文件的根视图谁的类是MyView.