Loading a XIB file to a UIView Swift

70,990

Solution 1

I uses this in one of our projects, might be useful to you

import UIKit

class RegisterPageView: UIView {
    
        class func instanceFromNib() -> RegisterPageView {
            return UINib(nibName: "RegisterPageView", bundle: nil).instantiateWithOwner(nil, options: nil)[0] as! RegisterPageView
        }
}
 

Solution 2

Using Swift 3.0

let viewFromNib: UIView? = Bundle.main.loadNibNamed("NibName", 
    owner: nil, 
    options: nil)?.first

Solution 3

Improved DevAndArtist UIView extension

public extension UIView
{
    static func loadFromXib<T>(withOwner: Any? = nil, options: [UINib.OptionsKey : Any]? = nil) -> T where T: UIView
    {
        let bundle = Bundle(for: self)
        let nib = UINib(nibName: "\(self)", bundle: bundle)

        guard let view = nib.instantiate(withOwner: withOwner, options: options).first as? T else {
            fatalError("Could not load view from nib file.")
        }
        return view
    }
}

Usage

let view = CustomView.loadFromXib()
let view = CustomView.loadFromXib(withOwner: self)
let view = CustomView.loadFromXib(withOwner: self, options: [UINibExternalObjects: objects])

External Objects discussion

Solution 4

Here is my approach (written in Swift 3.1):

protocol XibDesignable : class {}

extension XibDesignable where Self : UIView {

    static func instantiateFromXib() -> Self {

        let dynamicMetatype = Self.self
        let bundle = Bundle(for: dynamicMetatype)
        let nib = UINib(nibName: "\(dynamicMetatype)", bundle: bundle)

        guard let view = nib.instantiate(withOwner: nil, options: nil).first as? Self else {

            fatalError("Could not load view from nib file.")
        }
        return view
    }
}

extension UIView : XibDesignable {}

Now I simply can create any UIView subclass from a Xib (assuming there is one) like so MyCustomView.instantiateFromXib(). Remember to name your Xib file exactly as your UIView subclass and set the type of the main view in that Xib file correctly.


As soon as SE-0068 will be implemented one could drop the protocol and move the function directly into the UIView extension.


Just a note: The original post uses a commonly used pattern with a nested view. IMHO this is a bad pattern which does not utilize the resources and only creates unnecessary view hierarchy.

Solution 5

Swift 4.x

let myView = Bundle.main.loadNibNamed("yourXibView", owner: nil, options: nil)![0] as! UIView
Share:
70,990
Jimmy lemieux
Author by

Jimmy lemieux

Updated on November 10, 2021

Comments

  • Jimmy lemieux
    Jimmy lemieux over 2 years

    I am trying to load my XIB file into a UIView but I am having some trouble. I have the required override functions but they seem to be crashing. Saying this error, warning:

    could not load any Objective-C class information. This will significantly reduce the quality of type information available.

    I was wondering if someone could show me how to properly load the XIB file into a UIView

    import UIKit
    
    class Widget: UIView {
    
        let view = UIView()
    
        override init(frame: CGRect) {
            super.init(frame: frame)
    
            //call function
    
            loadNib()
    
        }
    
        required init?(coder aDecoder: NSCoder) {
            super.init(coder: aDecoder)
    
            loadNib()
    
            //fatalError("init(coder:) has not been implemented")
        }
    
        func loadNib() {
            let bundle = NSBundle(forClass: self.dynamicType)
            let nib = UINib(nibName: "nib", bundle: bundle)
            let view = nib.instantiateWithOwner(self, options: nil)[0] as! UIView
            view.frame = bounds
            view.autoresizingMask = [.FlexibleWidth, .FlexibleHeight]
            self.addSubview(view);  
        }
    }