Loading ViewController from xib file

江枫思渺然 提交于 2019-11-29 00:31:08

问题


I had a MyViewController.swift and a MyViewController.xib presenting the layout of MyViewController.

I tried different methods to load this view controller including:

//1
let myVC = UINib(nibName: "MyViewController", bundle:
       nil).instantiateWithOwner(nil, options: nil)[0] as? MyViewController

//2
let myVC = NSBundle.mainBundle().loadNibNamed("MyViewController", owner: self, options: nil)[0] as? MyViewController

//3
let myVC = MyViewController(nibName: "MyViewController", bundle: nil)

The third one is the only successful initialisation, but the previous two are causing error:

Terminating app due to uncaught exception 'NSUnknownKeyException',

reason: '[ setValue:forUndefinedKey:]: this class is not key value coding-compliant for the key XXX.

What's wrong with those loading methods?


回答1:


Swift 3

let myViewController = MyViewController(nibName: "MyViewController", bundle: nil)
self.present(myViewController, animated: true, completion: nil)

or push in navigation controller

self.navigationController!.pushViewController(MyViewController(nibName: "MyViewController", bundle: nil), animated: true)



回答2:


Notice the File's Owner. In your case, the File's Owner must be MyViewController, or it's sub-class.

And the following codes, if it executes in class Foo.

// If `self` is an instance of `Foo` class.
// In this case, `File's Owner` will be a `Foo` instance due to `self` parameter.
let myVC = NSBundle.mainBundle().loadNibNamed("MyViewController", owner: self, options: nil)[0] as? MyViewController

It assigns self as owner. So, the File's Owner is Foo, not MyViewController. Then, for Foo class, those IBOutlet cannot be connected to Foo. So, it throws exception.




回答3:


extension UIViewController {
    static func loadFromNib() -> Self {
        func instantiateFromNib<T: UIViewController>() -> T {
            return T.init(nibName: String(describing: T.self), bundle: nil)
        }

        return instantiateFromNib()
    }
}

Use it as the following:-

let testVC = TestVC.loadFromNib()



回答4:


The problem is not with the methods...you have probably kept an outlet(XXX) connected for some uielement and have removed it from corresponding controller...I am adding example below...

the above button is connected to controller now but when i comment outlet

my app crashes

so try to find outlet(xxx) that is missing from viewcontroller but is in xib file.Hope it helps :)




回答5:


I had the same problem. The automatically generated xib had a UIView in it. You have to delete the view, add new view controller to the xib, set the view controller class to the one you want and then connect the outlets. After all of this you can use the codes provided above to get an instance of this view controller, like this:

if let menuVC = Bundle.main.loadNibNamed("MenuViewController", owner: nil, options: nil)?.first as? MenuViewController {
            menuVC.profileType = profileType
            vc.present(menuVC, animated: true, completion: nil)
        }



回答6:


@AechoLiu's answer is great. I had the same question and answered it with the below fix.

Problem:

let vc1 = NSViewController(nibName: YDNibIdentifier.myplainvc, bundle: nil)

Fix:

let vc1 = MyPlainViewController(nibName: YDNibIdentifier.myplainvc, bundle: nil)

I had accidentally cast my Nib file to the wrong Clas ( NSViewController ), despite having it connected correctly inside the .xib file.




回答7:


Try below code,

//1

let nib = UINib(nibName: "MyViewController", bundle:nil)
myVC = nib.instantiateWithOwner(self, options: nil)[0] as? MyViewController

OR

myVC = nib.instantiateWithOwner(self, options: nil).first as? MyViewController

//2

let nib : NSArray = NSBundle.mainBundle().loadNibNamed("MyViewController", owner: self, options: nil)
myVC = nib.objectAtIndex(0) as? MyViewController

This will work.



来源:https://stackoverflow.com/questions/37046573/loading-viewcontroller-from-xib-file

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!