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?
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)
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.
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()
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)
}
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 ...
le bouton ci-dessus est connecté au contrôleur maintenant mais quand je commente la sortie
alors essayez de trouver la sortie (xxx) qui manque dans viewcontroller mais se trouve dans le fichier xib.Espoir que ça aide :)
@ 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.