Custom UIView from nib inside another UIViewController nib - IBOutlets - nil

I am trying to create a custom UIView that contains links to native IBOutlets. Then I want to put this custom UIView in a different tip.

I am doing additional logic in the UIView awakeFromNib custom method. Unfortunately, when I try to access IBOutlets in awakeFromNib , they are null.

Here's the setting:

  • I have a subclass of UIView , CustomView .
  • I have a custom .xib file with three subviews
  • In another nib (which belongs to the view controller) I dragged a UIView to the view and then changed the user class to CustomView .
  • I tried CustomView view in CustomView nib in IB to the custom class CustomView and connecting IBOutlets to the view, but they are still zero.
  • I tried setting the file owner to CustomView and connecting IBOutlets to the file owner, but they are still zero.
  • I also tried using another IBOutlet UIView *view , and then adding this as a subheading to self in awakeFromNib , but it also did nothing.

Here is the code:

 // 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"; } 
+7
ios objective-c uiviewcontroller uiview
source share
3 answers

I ended up using the steps in the last edited here , and they worked just fine.

You are using a regular UIView as the top level view in xib .

Then you set the owner of the file to a custom subclass ( CustomView ).

Finally, you add the line:

 [self addSubview:[[[UINib nibWithNibName:@"CustomView" bundle:nil] instantiateWithOwner:self options:nil] objectAtIndex:0]]; 

in the if (self != nil) block in both initWithCoder and initWithFrame .

Voila! IBOutlets connected and ready to work after a call. Really happy with the solution, but it was very difficult to dig out.

Hope this helps anyone.


EDIT : I updated the link to the one that is not dead. Since I never registered the full code, here is what it looks after modification:

 - (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"; } 

This pattern has become so common that I actually created a category on UIView called UIView+Nib that implements the following method:

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

Thus, the above code can be simplified to:

 [self addSubview:[UIView viewWithNibName:@"CustomView" owner:self]]; 

Note also that the code above can be reorganized even more, since the logic is exactly the same in initWithFrame: and initWithCoder: Hope this helps!

+19
source share

I assume the XIBs structure is something like this

 CustomView.xib CustomView UITextField -> linked to IBOutlet textField other views CustomViewController.xib CustomView 

If this is correct, then your CustomView will be created, but since it cannot be read from CustomView.xib, it does not have IBOutlets assigned.

However, if your CustomViewController.xib looks like this

 CustomViewController.xib CustomView UITextField -> linked to IBOutlet textField of CustomView 

then it should work. The IBOutlet of the CustomView instance must be set using CustomViewController.xib.

Better than setting any IBOutlets in CustomViewController.xib, would implement awakeAfterUsingCoder: in your CustomView and create a replacement object by loading your CustomView.xib there. Thus, your CustomView remains truly ordinary, and you do not need to edit other XIBs to change the structure, add / remove IBOutlets, etc.

+1
source share

As in the case of Dr. Shark, this is probably because the user view nib was loaded when loading from another nib (nib nib loading), so we need to create it manually. In fast code, it will look like this:

  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.bounds.addSubview(self.customview!) } 
+1
source share

All Articles