简体   繁体   中英

Load custom UIView from xib programmatically

I have created a custom UIView in MySample.xib . I have added the class MyView to the File Owner of xib.

MyView.swift

class MyView: UIView {

    @IBOutlet var view: UIView!

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

        setup()
    }

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

        setup()
    }

    func setup() {
        NSBundle.mainBundle().loadNibNamed("MySample", owner: self, options: nil)            
        self.addSubview(self.view)
    }
}

I am now loading this MyView from MyController file like this:

MyController.swift

class MyController: UIViewController {
    init() {
        super.init(nibName: nil, bundle: nil)

        view.addSubview(MyView())

    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}

Now to display this view, I am using to following code from another controller's UIButton :

presentViewController(MyController(), animated: true, completion: nil)

This does display the view on screen. But the problem is, it doesn't accept any user interaction. In my custom view, I have a UITableView which does display the data but it doesn't scroll or get tapped due to lack of user interaction.

Any idea what I am doing wrong?

There are some unnecessary things in your example.

I am still not sure what are you trying to do, but if you want to add a custom view from xib to your view controller then:

  1. Create a view in a xib file , you don't need to override init , and you can't init view from xib using the default init UIView() , so please remove init method from your MyView class.

  2. In your xib make sure that your view that you see in the IB is of the class type you want to use (i guess MyView class).

  3. In your view controller init the view like this:

     class MyController: UIViewController { override func viewDidLoad() { super.viewDidLoad() //Get all views in the xib let allViewsInXibArray = NSBundle.mainBundle().loadNibNamed("MySample", owner: self, options: nil) //If you only have one view in the xib and you set it's class to MyView class let myView = allViewsInXibArray.first as! MyView //Set wanted position and size (frame) myView.frame = self.view.bounds //Add the view self.view.addSubview(myView) //TODO: set wanted constraints. } } 

Instead of linking xib File's Owner class to MyView , I have to change the class of root view in xib to MyView . Then based on @Oleg Sherman code, it works perfectly with small changes of adding MyView() as owner to get all it's events, otherwise it will throw an error this class is not key value coding-compliant for the key ****. :

let allViewsInXibArray = NSBundle.mainBundle().loadNibNamed("MySample", owner: MyView(), options: nil)

Using File's Owner class to MyView is only required when you have to use the xib in Storyboard.

Not sure if there is a workaround to use File's Owner class to MyView when programmatically loading xib from custom controller like in my original question.

You don't have to re-instantiate this twice already if you using the design pattern .

It's so simple. Just write:

class MyController: UIViewController {

override func viewDidLoad() {
    super.viewDidLoad()

    //Get all views in the xib
    let view = MyView() 
    self.view.addSubview(myView)

    //TODO: set wanted constraints.
}}

And It will work.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM