2

I'm looking for a way to make nibs that I can then embed and reuse inside a storyboard with all the IBOutlets correctly instantiated. I was able to get it working using a modified version of this tutorial.

The steps for getting this to work are:

  1. Make a custom view subclass and corresponding nib
  2. Set File's Owner to the custom view subclass
  3. Add a UIView as a direct descendent of the nib's view (this is our Content View)
  4. Create an IBOutlet in your view class called contentView of type UIView and content the content view in the nib to that outlet
  5. In awakeFromNib do the following:

    override func awakeFromNib() {
        super.awakeFromNib() //call super
        NSBundle.mainBundle().loadNibNamed("MyView", owner: self, options: nil)
        self.contentView.translatesAutoresizingMaskIntoConstraints = false
        self.addSubview(self.contentView)
    
        self.addEdgeConstraintWithAttribute(.Left, withSubview: self.contentView)
        self.addEdgeConstraintWithAttribute(.Top, withSubview: self.contentView)
        self.addEdgeConstraintWithAttribute(.Right, withSubview: self.contentView)
        self.addEdgeConstraintWithAttribute(.Bottom, withSubview: self.contentView)
    }
    

This process works fine but I don't understand HOW works. And is there a better way of achieving the same thing?

barndog
  • 6,975
  • 8
  • 53
  • 105

1 Answers1

2

This all magic comes from the awakeFromNib from NSNibAwaking protocol.

"The -awakeFromNib method is called for every object that is instantiated when a nib file is loaded..." - e.James

Lets say, you made a class and nib with the name of MyView and done all the above steps, Now when you add a UIView in your storyboard and set its class to MyView and run the app. Here's what happens.

  • You storyboard loads all views and also calls awakeFromNib for your MyView.
  • Your awakeFromNib then triggers the loading of nib named MyView.
  • You get the content view from Nib instantiated views and add it to storyboard instantiated view and set its constraints.
  • Notice the loadNibNamed method, you're sending self as owner, so when the nib is unarchived and loaded, it sets all the IBOutlets to the sent self, that's why your IBOutlet worked i.e self.contentView because contentView now has view from nib.
Community
  • 1
  • 1
Adil Soomro
  • 37,609
  • 9
  • 103
  • 153
  • Are two different view instances getting loaded or rather is it two different nibs (one from the storyboard, one from the nib) that then get the `IBOutlet` properties merged together? – barndog Sep 13 '15 at 02:35
  • Yes. There's one and that's from storyboard. It had nothing initially as subviews, so it loaded the nib so it could load its subviews. I've edited it to make it less confusing. – Adil Soomro Sep 13 '15 at 06:45