Reputation: 237
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.
Upvotes: 0
Views: 3459
Reputation: 2774
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!
Upvotes: 0
Reputation: 792
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.
Upvotes: 1
Reputation: 237
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)
Upvotes: 0
Reputation: 11123
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)
Upvotes: 0
Reputation: 66
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)
Upvotes: 1
Reputation: 10951
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)
}
Upvotes: 1