0

Ive been searching for a while for a simple example on how to reuse views from xib files in my storyboard but all i find was outdated or dosen't solve my problem the situation is that I has simple:

  • I have a viewController in my storyboard
  • I dragged to it two view from the library
  • I had created a myCustomView.xib and myCustomView.swift file (they are empty now)
  • I have I button on viewController (so the tree (two view and one button) are setting together on the viewController in the storyboard)
  • the question is: I want one view to be loaded dynamically on app launch and the other one to be loaded on button click
  • an other question: how can I connect myCustomView to that viewController

thank you

2 Answers 2

4

I've implemented an extension for UIView:

extension UIView {

    static func createInstance<T: UIView>(ofType type: T.Type) -> T {
        let className = NSStringFromClass(type).components(separatedBy: ".").last
        return Bundle.main.loadNibNamed(className!, owner: self, options: nil)![0] as! T
    }

}

In this way, wherever you can load your custom view in this way:

func override viewDidLoad() {
    super.viewDidLoad()
    let customView = UIView.createInstance(ofType: CustomView.self) 
    self.view.addSubview(customView)
}
Sign up to request clarification or add additional context in comments.

4 Comments

If I had a button on myCustomView! where would I put the handler of the button? on myCustomView or on the viewController that instantiate the view
In your customView, of course. Then you have several way to "notify" related view controller.
Nice answer, but is the type parameter really necessary? Can't your infer that from the generic argument T? Maybe using T.self?
I cant get it to run this line let customView = UIView.createInstance(ofType: CustomView.self) says Cannot convert type UIView! to expected argument type UIView.Type
1

Add bellow code in your custom view class

class MyCustomView: UIView {


   @IBOutlet var contentView: UIView! // take view outlet

    override init(frame: CGRect) {
        super.init(frame: frame)
        xibSetup()
    }

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        xibSetup()
    }


    func xibSetup() {
        contentView = loadViewFromNib()

        // use bounds not frame or it'll be offset
        contentView!.frame = bounds

        //Make the view stretch with containing view
        contentView!.autoresizingMask = [UIViewAutoresizing.flexibleWidth, UIViewAutoresizing.flexibleHeight]

        // Adding custom subview on top of our view (over any custom drawing > see note below)
        addSubview(contentView!)
        layoutIfNeeded()
    }

    override func layoutIfNeeded() {
        super.layoutIfNeeded()
        print("layoutIfNeeded")


    }

    func loadViewFromNib() -> UIView! {
        let bundle = Bundle(for: type(of: self))
        let nib = UINib(nibName: String(describing: type(of: self)), bundle: bundle)
        let view = nib.instantiate(withOwner: self, options: nil)[0] as! UIView
        return view
    }
}

Add this class as superclass view in storyboard.

2 Comments

I see this is the myCustomView.swift, what if I want to instantiate this view somewhere in a viewController what do I have to do?
This works completely well! Of course, you will need to link correctly your nib first, but I was having troubles to set this part. Thanks!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.