来自另一个UIViewController的nib中的nib的自定义UIView - IBOutlets是nil

Dr.*_*ula 8 objective-c uiviewcontroller uiview ios

我正在尝试创建一个自定义UIView,它保存对自己的IBOutlets的引用.然后我想将这个自定义UIView放入另一个笔尖.

我在自定义UIView的awakeFromNib方法中做了一些额外的逻辑.不幸的是,当我尝试访问IBOutletsawakeFromNib,它们是零.

这是设置:

  1. 我有一个UIView子类,CustomView.
  2. 我有一个.xib包含三个子视图的自定义文件
  3. 在另一个nib(属于视图控制器)中,我将a UIView拖到视图上,然后将自定义类更改为CustomView.
  4. 我尝试将CustomViewIB 中的nib中的视图设置为自定义类CustomView并连接IBOutlets到视图,但它们仍然是零.
  5. 我尝试将文件所有者设置为CustomView并连接IBOutlets到文件的所有者,但它们仍然是零.
  6. 我也尝试使用其他IBOutlet UIView *view,然后补充说,作为一个子视图selfawakeFromNib,但还没有做任何事情.

这是代码:

// 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";
}
Run Code Online (Sandbox Code Playgroud)

Dr.*_*ula 20

我结束了使用在最近编辑的步骤,在这里和他们的工作精美.

您可以使用plain UIView作为顶级视图xib.

然后,将文件所有者设置为自定义子类(CustomView).

最后,添加一行:

[self addSubview:[[[UINib nibWithNibName:@"CustomView" bundle:nil] instantiateWithOwner:self options:nil] objectAtIndex:0]];
Run Code Online (Sandbox Code Playgroud)

在和if (self != nil)两个块中.initWithCoderinitWithFrame

瞧!在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";
}
Run Code Online (Sandbox Code Playgroud)

这种模式已经变得如此普遍,以至于我实际上在UIView被调用上创建了一个类别UIView+Nib,它实现了以下方法:

+ (UIView *)viewWithNibName:(NSString *)nibName owner:(id)owner {
    return [[[UINib nibWithNibName:nibName bundle:nil]
            instantiateWithOwner:owner options:nil]
            objectAtIndex:0];
}
Run Code Online (Sandbox Code Playgroud)

所以上面的代码可以简化为:

[self addSubview:[UIView viewWithNibName:@"CustomView" owner:self]];
Run Code Online (Sandbox Code Playgroud)

另请注意,上面的代码可以进行更多重构,因为逻辑在initWithFrame:和中完全相同initWithCoder:.希望有所帮助!

  • "使用**普通的UIView**作为顶级视图"< - 非常重要!如果你使顶级视图也是你的`CustomView`,那么它会一直递响直到堆栈爆炸.不是那个*我*当然这样做了......这是一个朋友. (7认同)