web-dev-qa-db-fra.com

Chargement de ViewController à partir d'un fichier xib

J'ai eu un MyViewController.Swift et un MyViewController.xib présentant la mise en page de MyViewController.

J'ai essayé différentes méthodes pour charger ce contrôleur de vue, notamment:

//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)

La troisième est la seule initialisation réussie, mais les deux précédentes causent une erreur:

Arrêt de l'application en raison d'une exception non interceptée 'NSUnknownKeyException',

raison: '[setValue: forUndefinedKey:]: cette classe n'est pas compatible avec le codage des valeurs de clé pour la clé XXX.

Quel est le problème avec ces méthodes de chargement?

27
bluenowhere

Swift

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

ou pousser le contrôleur de navigation

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

File's Owner

Remarquez le File's Owner. Dans votre cas, le File's Owner doit être MyViewController, ou c'est sub-class.

Et les codes suivants, s’il s’exécute dans la classe 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

Il assigne self comme owner. Alors le File's Owner est Foo, pas MyViewController. Ensuite, pour Foo class, ces IBOutlet ne peuvent pas être connectés à Foo. Donc, il lève une exception.

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

        return instantiateFromNib()
    }
}

Utilisez-le comme suit: -

let testVC = TestVC.loadFromNib()
7
SamehDos

J'ai eu le même problème. Le xib généré automatiquement contenait un UIView. Vous devez supprimer la vue, ajouter un nouveau contrôleur de vue à la bibliothèque xib, définir la classe de contrôleur de vue sur celle de votre choix, puis connecter les prises. Après tout cela, vous pouvez utiliser les codes fournis ci-dessus pour obtenir une instance de ce contrôleur de vue, comme ceci:

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

Le problème n’est pas avec les méthodes ... vous avez probablement gardé une prise (XXX) connectée pendant un certain temps et l’avez retirée du contrôleur correspondant ... j’ajoute un exemple ci-dessous ... enter image description here

le bouton ci-dessus est connecté au contrôleur maintenant mais quand je commente la sortie enter image description here

mon application se bloque enter image description here

enter image description here

alors essayez de trouver la sortie (xxx) qui manque dans viewcontroller mais se trouve dans le fichier xib.Espoir que ça aide :)

2
Sanman

@ La réponse d'AechoLiu est excellente. J'ai eu la même question et a répondu avec le correctif ci-dessous.

Problème:

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

Correction:

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

J'avais accidentellement jeté mon fichier Nib sur la mauvaise Clas (NSViewController), malgré le fait qu'il soit correctement connecté à l'intérieur du fichier .xib.

0
rustyMagnet