我正在尝试创建一个自定义UIView,它保存对自己的IBOutlets的引用。然后我想将这个自定义UIView放入另一个笔尖。
我在自定义UIView的awakeFromNib
方法中做了一些额外的逻辑。不幸的是,当我尝试访问IBOutlets
中的awakeFromNib
时,它们是零。
以下是设置:
UIView
子类CustomView
。.xib
文件UIView
拖到视图上,然后将自定义类更改为CustomView
。CustomView
笔尖中的视图设置为自定义类CustomView
并将IBOutlets
连接到视图,但它们仍为零。CustomView
并将IBOutlets
连接到文件的所有者,但它们仍为零。 IBOutlet UIView *view
,然后将其作为子视图添加到self
中的awakeFromNib
,但也没有做任何事情。以下是代码:
// CustomView.h
@interface CustomView : UIView
@property (nonatomic, retain) IBOutlet UITextField *textField;
@property (nonatomic, retain) IBOutlet UIView *subview1;
@property (nonatomic, retain) IBOutlet UIView *subview2;
// CustomView.m
@implementation CustomView
@synthesize textField, subview1, subview2;
- (id)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
[[NSBundle mainBundle] loadNibNamed:@"CustomView" owner:self options:nil];
}
return self;
}
- (id)initWithCoder:(NSCoder *)aDecoder {
self = [super initWithCoder:aDecoder];
if (self) {
}
return self;
}
- (void)awakeFromNib {
[super awakeFromNib];
[self setup];
}
- (void)setup {
// Fails because self.textField is nil
self.textField.text = @"foo";
}
答案 0 :(得分:20)
我最终使用了最新编辑here中的步骤,并且效果很好。
您使用普通UIView
作为xib
中的顶级视图。
然后将文件所有者设置为自定义子类(CustomView
)。
最后,添加一行:
[self addSubview:[[[UINib nibWithNibName:@"CustomView" bundle:nil] instantiateWithOwner:self options:nil] objectAtIndex:0]];
位于if (self != nil)
和initWithCoder
的{{1}}块中。
瞧! initWithFrame
已经联系起来并准备好在通话结束后继续。对解决方案非常满意,但是很难挖掘出来。
希望这有助于其他任何人。
编辑:我将链接更新为尚未死亡的链接。由于我从未拼写过完整的代码,因此修改后的内容如下:
IBOutlets
这种模式已经变得非常普遍,我实际上在名为- (id)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
UIView *nib = [[[UINib nibWithNibName:@"CustomView" bundle:nil] instantiateWithOwner:self options:nil] objectAtIndex:0];
[self addSubview:nib];
}
return self;
}
- (id)initWithCoder:(NSCoder *)aDecoder {
self = [super initWithCoder:aDecoder];
if (self) {
UIView *nib = [[[UINib nibWithNibName:@"CustomView" bundle:nil] instantiateWithOwner:self options:nil] objectAtIndex:0];
[self addSubview:nib];
}
return self;
}
- (void)awakeFromNib {
[super awakeFromNib];
[self setup];
}
- (void)setup {
// Doesn't fail because life is awesome
self.textField.text = @"foo";
}
的{{1}}上创建了一个类别,它实现了以下方法:
UIView
所以上面的代码可以简化为:
UIView+Nib
另请注意,上述代码可以进行更多重构,因为+ (UIView *)viewWithNibName:(NSString *)nibName owner:(id)owner {
return [[[UINib nibWithNibName:nibName bundle:nil]
instantiateWithOwner:owner options:nil]
objectAtIndex:0];
}
和[self addSubview:[UIView viewWithNibName:@"CustomView" owner:self]];
中的逻辑完全相同。希望有所帮助!
答案 1 :(得分:1)
我假设XIB的结构是这样的
CustomView.xib
CustomView
UITextField -> linked to IBOutlet textField
other views
CustomViewController.xib
CustomView
如果这是正确的,那么将创建您的CustomView,但因为它不是从CustomView.xib读取的,所以它没有分配任何IBOutlets。
但是,如果您的CustomViewController.xib如下所示
CustomViewController.xib
CustomView
UITextField -> linked to IBOutlet textField of CustomView
然后这应该工作。 CustomView实例的IBOutlet应该由CustomViewController.xib设置。
比在CustomViewController.xib中设置任何IBOutlets更好的方法是在您的CustomView中实现awakeAfterUsingCoder:并通过在那里加载CustomView.xib来创建替换对象。这样,您的CustomView仍然是真正的自定义,您不必编辑其他XIB来更改结构,添加/删除IBOutlet等。
答案 2 :(得分:1)
正如Acula博士的回答,这可能是因为自定义视图的nib在从另一个nib(嵌套nib加载)加载时是延迟加载的,所以我们需要手动实例化它。在swift代码中将如下所示:
override func awakeFromNib() {
super.awakeFromNib()
self.customview = UINib(nibName: "CustomViewNib", bundle: nil).instantiateWithOwner(self, options:nil)[0] as! UIView
self.customview?.frame = self.viewContainer.bounds
self.viewContainer.addSubview(self.customview!)
}