0
votes

I'm trying to load a nib programmatically without using IBOutlets in storyboard.

I've set the file owner's custom class and created outlets for the images and labels. I've created an instance of UINib and called instantiateWithOwner in my custom class to manually load the nib. Now I'm trying to load the nib on an uitableviewcontroller.

My question is how to load that xib on a view controller without adding a uiview to a view controller using storyboard and without connecting outlets to the uiview.

There are several questions and tutorials for how load the nib using storyboard and IBOutlets, which is straightforward.

Can anyone tell me how to go about this programmatically, in swift?

Note: I have two viewcontrollers in my project. VC1 has a collectionView with an image and a label. I'm using a xib and a custom class to display the selected collectionView in VC2.

6

6 Answers

0
votes

You don't necessarily have to have an owner setup. You can simply instantiate the nib and reference the top level objects created by it. Having said that, if you do pass self as the owner and have outlets connected, that works as well. It's worth noting that if you instantiate the nib multiple times, the value of the outlets is set to the new instances each time. If you want to reference the prior ones you'll have to capture them in some other property.

    // Create a UINib object for a nib named MyNib in the main bundle
    let nib = UINib(nibName: "MyNib", bundle: nil)

    // Instante the objects in the UINib
    let topLevelObjects = nib.instantiateWithOwner(self /*or nil*/, options: nil)

    // Use the top level objects directly...
    let firstTopLevelObject = topLevelObjects[0]

    // Or use any IBOutlets
    doSomeStuff(self.someOutletProperty)
1
votes

You can take a top view form XIB and put it everywhere

override func viewDidLoad() {
    super.viewDidLoad()
    let calendar = UINib(nibName: "<<NibFileName>>", bundle: nil).instantiateWithOwner(nil, options: nil)[0] as! UIView
    view.addSubview(calendar)
}
1
votes

You can use this method :

Method:

public static func getViewFromNib(nibName:String)-> UINib{
    let uiNib = UINib(nibName: nibName, bundle: nil)
    return uiNib 
}

Usage :

    let customView = getViewFromNib.instantiateWithOwner(ownerOrNil, options: nil) as! UIView
    view.addSubview(customView)
1
votes

I have found another solution from here and adapted for me (Swift 2):

let myView = NSBundle.mainBundle().loadNibNamed("myView", owner: self, options: nil).first as! myView
self.view.addSubview(myView)
myView.translatesAutoresizingMaskIntoConstraints = false
self.view.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("H:|-0-[view]-0-|", options: NSLayoutFormatOptions(rawValue: 0), metrics: nil, views: ["view":myView]))
self.view.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:|-0-[view]-0-|", options: NSLayoutFormatOptions(rawValue: 0), metrics: nil, views: ["view":myView]))
myView.myButton.setTitle("myTitle", forState: .Normal)

The constraints where created progammatically. The outlets created in the xib are easily available in the main viewController class.

Anyway, this code surely be improved. I'm a rough programmer.

0
votes

Thanks for the answers to this question. They are all good. I've accepted the one that was easiest for me to implement. Here is a different approach that will also work for certain situations:

    var myView: myCoolView = myCoolView()  // subclass of uiview with xib

Then, add in ViewDidLoad:

    myView.frame = CGRectMake(0, 64, self.view.frame.size.width, 175)
    myView.titleLabel.text = stringOne
    myView.backgroundImage.image = imageOne
    myView.contentMode = UIViewContentMode.ScaleAspectFill
    myView.autoresizingMask = UIViewAutoresizing.FlexibleBottomMargin | UIViewAutoresizing.FlexibleHeight | UIViewAutoresizing.FlexibleRightMargin | UIViewAutoresizing.FlexibleLeftMargin | UIViewAutoresizing.FlexibleTopMargin | UIViewAutoresizing.FlexibleWidth
    self.view.addSubview(myView)
0
votes

The best answer didn't work for me. I've just done:

let newView = Bundle.main.loadNibNamed("MyNib", owner: self, options: nil)?.first as! UIView
    self.view.addSubview(newView)
    newView.translatesAutoresizingMaskIntoConstraints = false
    self.view.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|-0-[view]-0-|", options: NSLayoutFormatOptions(rawValue: 0), metrics: nil, views: ["view":newView]))
    self.view.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:|-0-[view]-0-|", options: NSLayoutFormatOptions(rawValue: 0), metrics: nil, views: ["view":newView]))

works like a charm

And if you need access to a element you can do:

newView.myButton.setTitle("myTitle", forState: .Normal)

Good coding!