ios - from - Cargando ViewController desde un archivo xib
load xib swift 4 (6)
Tuve un MyViewController.swift
y un MyViewController.xib
presentando el diseño de MyViewController.
Probé diferentes métodos para cargar este controlador de vista, incluyendo:
//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 tercera es la única inicialización exitosa, pero las dos anteriores están causando un error:
Finalizando la aplicación debido a la excepción no detectada ''NSUnknownKeyException'',
motivo: ''[setValue: forUndefinedKey:]: esta clase no es compatible con el valor de clave para la clave XXX.
¿Qué hay de malo con esos métodos de carga?
El problema no es con los métodos ... probablemente haya conectado un tomacorriente (XXX) para algún elemento y lo haya retirado del controlador correspondiente ... A continuación, agrego un ejemplo ...
el botón de arriba está conectado al controlador ahora, pero cuando comento salida
así que trata de encontrar la salida (xxx) que falta en el controlador de vista pero que se encuentra en el archivo xib.
Intente código debajo,
// 1
let nib = UINib(nibName: "MyViewController", bundle:nil)
myVC = nib.instantiateWithOwner(self, options: nil)[0] as? MyViewController
O
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
Esto funcionará.
Yo tuve el mismo problema. El xib generado automáticamente tenía un UIView en él. Debe eliminar la vista, agregar el nuevo controlador de vista a la xib, configurar la clase del controlador de vista a la que desea y luego conectar las salidas. Después de todo esto, puede usar los códigos proporcionados anteriormente para obtener una instancia de este controlador de vista, como este:
if let menuVC = Bundle.main.loadNibNamed("MenuViewController", owner: nil, options: nil)?.first as? MenuViewController {
menuVC.profileType = profileType
vc.present(menuVC, animated: true, completion: nil)
}
Observe el File''s Owner
. En su caso, el File''s Owner
debe ser MyViewController
, o su sub-class
.
Y los siguientes códigos, si se ejecutan en clase 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
Se asigna a self
como owner
. Por lo tanto, el File''s Owner
es Foo
, no MyViewController
. Entonces, para la clase Foo
, esos IBOutlet
no se pueden conectar a Foo
. Por lo tanto, arroja excepción.
Swift 3
let myViewController = MyViewController(nibName: "MyViewController", bundle: nil)
self.present(myViewController, animated: true, completion: nil)
o presiona el controlador de navegación
self.navigationController!.pushViewController(MyViewController(nibName: "MyViewController", bundle: nil), animated: true)
extension UIViewController {
static func loadFromNib() -> Self {
func instantiateFromNib<T: UIViewController>() -> T {
return T.init(nibName: String(describing: T.self), bundle: nil)
}
return instantiateFromNib()
}
}
Úsalo como lo siguiente:
let testVC = TestVC.loadFromNib()