xcode - IBOutlet es nulo, pero está conectado en el guión gráfico, Swift
uistoryboard null (30)
2019, UNA POSIBILIDAD PARA ESTE HORRIBLE PROBLEMA:
-
Supongamos que tiene una vista de contenedor que muestra algún tipo de reloj. Así que tienes
Reloj de clase: UIViewController
De hecho, lo usa en varios lugares de la aplicación .
En la pantalla principal, en la pantalla de detalles, en la pantalla de edición.
Tienes una aplicación moderna complicada similar a Snapchat.
De hecho,
Clock
puede cargarse
más de una vez
al
mismo tiempo en
algún lugar de la
misma pantalla
.
(Tal vez está oculto en algunos casos).
Comienza a trabajar en una instancia de
Clock
en uno de sus muchos guiones gráficos.
En ese guión gráfico agrega una etiqueta, NewLabel.
Naturalmente, agrega la salida en el código. Todo debería funcionar. Todos los demás puntos de venta funcionan perfectamente.
Definitivamente has vinculado la salida.
Pero la aplicación se bloquea con NewLabel como nula.
Xcode le dice claramente "olvidó conectar la toma de corriente".
¡La razón es esta .......... tienes "NewLabel" en solo uno de los usos de Storyboard de Clock!
El accidente es en realidad de >>> otro lugar <<<< estás usando Clock !!!!
¡Xcode no te dice que el accidente es de otro lugar, no de donde estás trabajando!
El bloqueo en realidad no es del lugar donde estás trabajando, ¡es de otro guión gráfico, donde no hay ningún elemento "NewLabel" en ese guión gráfico!
Frustrante.
Usando Swift 1.1 y Xcode 6.2.
Tengo un UIStoryboard que contiene una subclase
UIViewController
personalizada y singular.
En él, tengo una conexión
@IBOutlet
de tipo
UIView
desde ese controlador a una
subclase
UIView
en el guión gráfico.
También tengo salidas similares para subvistas de esa vista.
Ver figura A.
Pero en tiempo de ejecución, estas propiedades son nulas (Figura B). Aunque he asegurado que he conectado los enchufes en Interface Builder.
Pensamientos :
- ¿Es posible que debido a que estoy usando una subclase de una subclase, algo se confunde con la inicialización? No estoy anulando ningún inicializador
-
awakeFromNib:
no se llama por alguna razón - Tal vez no se conecta a subvistas en subvistas
Cosas que he probado:
-
Coincidencia de los tipos de elementos
@IBOutlet
y storyboard exactamente (en lugar deUIView
) - Eliminar propiedad y salida y volver a agregarlos
Figura A *
Figura B
* El código oculto en la
Figure A
es:
@IBOutlet private var annotationOptionsView: UIView!
@IBOutlet private var arrivingLeavingSwitch: UISegmentedControl!
Gracias.
-
seleccione archivos de controlador de vista
.h
y.m
- eliminar la referencia de esos archivos
- vuelva a agregar los archivos a su árbol de proyecto
- abrir el guión gráfico, eventualmente reconstruir el proyecto
¿Has intentado ejecutar Producto> Limpiar? Resuelto un problema muy similar para mí.
¿Instanciaste tu controlador de vista desde un Storyboard o NIB, o lo instanciaste directamente a través de un inicializador?
Si crea una instancia de su clase directamente con el inicializador, las salidas no se conectarán. Interface Builder crea instancias personalizadas de sus clases y las codifica en NIB y Storyboards para la decodificación repetida, no define las clases en sí mismas. Si este fue su problema, solo necesita cambiar el código donde crea su controlador para utilizar los métodos en UIStoryboard o UINib.
El guión gráfico no reconocía más cosas de IU que le agregué. En tiempo de ejecución, todas las referencias eran nulas. Así que borré mi carpeta de datos derivados y luego esas conexiones funcionaron nuevamente.
En mi caso, la aplicación comenzó a fallar de repente.
La depuración reveló que todos los puntos de venta todavía eran
nil
en el momento de
viewDidLoad()
.
Mi aplicación todavía usa plumillas (no guiones gráficos) para la mayoría de los controladores de vista. Todo estaba en su lugar, todos los enchufes estaban correctamente conectados. Lo comprobé dos veces.
Por lo general, instanciamos nuestros controladores de vista como
// creating instance
let controller = CustomViewController()
... que por alguna razón parece funcionar siempre que el .xib tenga el mismo nombre que la clase de controlador de vista (aunque no estoy seguro de cómo funciona). No estamos llamando a
init(nibName:bundle:)
con argumentos nulos, o anular
init()
para hacerlo en
self
como se suele sugerir ...).
Entonces intenté llamar explícitamente
// connecting view/xib with controller instance
let bundle = Bundle(for: type(of: controller))
bundle.loadNibNamed("CustomViewControllerView", owner: controller, options: nil)
... solo para ser recibido con el error de excepción de tiempo de ejecución:
*** Finalización de la aplicación debido a la excepción no detectada ''NSInternalInconsistencyException'', razón: ''No se pudo cargar NIB en el paquete:'' NSBundle </ Users / nicolasmiari / Library / Developer / CoreSimulator / Devices / 3DA3CF21-108D-498F-9649-C4FC9E3C1A8D / data /Containers/Bundle/Application/C543DDC1-AE86-4D29-988C-9CCE89E23543/MyApp.app> (cargado) ''con el nombre'' MYCustomViewController ''''
Y luego , lo vi:
La casilla de verificación "Membresía de destino" del archivo .xib no estaba marcada.
Debe haber sucedido al resolver uno de los frecuentes conflictos de fusión con respecto al archivo del proyecto Xcode.
Apple definitivamente necesita crear un formato de archivo de proyecto que sea más compatible con SCM.
En mi caso, sucedió porque
loadView
método
loadView
en mi subclase ViewController, pero olvidé agregar
[super loadView]
-(void)loadView {
// blank
}
Cuando anula el método
loadView
, es su responsabilidad iniciar sus subvistas.
Como lo anula, las vistas del generador de interfaces no tienen la oportunidad de convertirse en objetos de cacao y, por lo tanto, las salidas permanecen nulas.
Si implementa loadView en su subclase de controlador de vista, entonces es su responsabilidad cargar los elementos de la interfaz de usuario del guión gráfico / xib en el código.
O simplemente llama
[super loadView];
Para que la superclase tenga la oportunidad de cargar storyboard / xib en el código.
Esto me estaba sucediendo con mi celda de vista de colección personalizada. Resulta que tuve que reemplazar mi método registerClassforReuseIdentifier con registerNib. Eso me lo arregló.
Esto me sucedió porque accidentalmente estaba instanciando mi controlador de vista directamente en lugar de instanciarlo a través del guión gráfico.
Si
MyViewController()
instancia directamente a través de
MyViewController()
, las salidas no se conectarán.
Me encuentro con este problema recientemente! Aquí está mi pensamiento. El problema no es sobre su guión gráfico o cualquier problema de enlace. Se trata de cómo iniciar su ViewController. Especialmente cuando está usando Swift. (No hay casi nada en el editor cuando crea un archivo de clase)
Simplemente usando
init()
de super class no puede iniciar nada de lo que trabajó con el storyboard.
Entonces, lo que debe hacer es cambiar la inicialización de ViewController.
Reemplace
let XXViewController = XXViewController()
por
let XXViewController = UIStoryboard(name: "Main", bundle: NSBundle.mainBundle()).instantiateViewControllerWithIdentifier("XXViewController") as! XXViewController
let XXViewController = UIStoryboard(name: "Main", bundle: NSBundle.mainBundle()).instantiateViewControllerWithIdentifier("XXViewController") as! XXViewController
Esto le dice al programa que vaya al guión gráfico y encuentre XXViewController e inicia todos los
IBOutlet
en su guión gráfico.
Espero que esta ayuda ~ GL
Otro caso más que acabo de encontrar. Cambié el nombre de mi clase para UIViewController, pero olvidé cambiar el nombre del archivo .xib donde se creó la interfaz.
Una vez que entendí esto e hice que los nombres de los archivos reflejaran el nombre de la clase, ¡todo estuvo bien!
Espero que ayude a alguien.
Otro caso:
Sus puntos de venta no se configurarán hasta que la vista del controlador de vista esté realmente instanciada, lo que en su caso probablemente suceda poco después de initWithNibName: paquete: en ese punto, todavía serán nulos. Cualquier configuración que haga que involucre esos puntos de venta debería estar sucediendo en el método -viewDidLoad de su controlador de vista.
Para Swift 3.
let initialVC = InitialVC()
Para mí, esto ocurrió cuando accidentalmente declaró la clase de mi controlador de vista como
class XYZViewController: UINavigationController {
}
(es decir, como
UINavigationController
no como
UIViewController
).
Xcode no
viewDidLoad
este error, la clase parece compilarse bien y anula funciones como
viewDidLoad
,
viewWillAppear
, etc., todo funciona correctamente.
Pero ninguno de los
IBOutlet
se conecta.
Cambiar la declaración a
class XYZViewController: UIViewController {
}
Lo arreglé por completo.
Para mí, esto se estaba bloqueando porque
containerView
era nulo.
Aquí está mi código con Crash .
if isViewLoaded && view.window != nil {
//self.annotationOptionsView.
}
Lo que faltaba era llamar a
super.loadView()
.
Así que agregarlo resolvió el problema para mí.
Código fijo :
let newVC = MYCustomViewController()
Para mí, tuve el mismo error en un guión gráfico localizado, se agregó un elemento en una configuración regional y no en la otra, por lo que tenía una referencia nula para ese elemento cuando cambié a la configuración regional del elemento faltante, tuve que eliminar la localización (redundante) para ese guión gráfico usando https://.com/a/42256341/1356559 .
Por lo general, esto sucede porque su controlador de vista aún no ha cargado su jerarquía de vista.
Un controlador de vista solo carga su jerarquía de vista cuando algo le envía el mensaje de
view
.
El sistema hace esto cuando es el momento de poner realmente la jerarquía de vistas en la pantalla, lo que sucede después de que cosas como
prepareForSegue:sender:
y
viewWillAppear:
han regresado.
Como su VC aún no ha cargado su jerarquía de vistas, sus puntos de venta siguen siendo nulos.
Puede forzar al VC a cargar su jerarquía de vistas diciendo
_ = self.view
.
Primero debe cargar la jerarquía de vistas para crear instancias de los puntos de venta en el guión gráfico. Para esto, puede llamar manualmente a los métodos loadView o loadViewIfNeeded.
Puede llamar a
controller.view
para forzar la carga de la vista para inicializar los IBOutlets, luego podrá asignar los valores.
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject!) {
if (segue.identifier == "identifier") {
let controller = segue.destinationViewController as! YourController
let _ = controller.view //force to load the view to initialize the IBOutlets
controller.your_IBOutlet_property = xxx
...
controller.delegate = self
}
}
Puede validar si la vista is está cargada.
let newVC = MYCustomViewController(nibName: "MYCustomViewController", bundle: .main)
Si crea una instancia del
view controller
mediante programación.
Luego intenta crearlo como a continuación
func configureView() {
let _ = self.view
}
en lugar de directamente
let initialVC = self.storyboard?.instantiateViewController(withIdentifier: "InitialVC") as! InitialVC
Esto funcionó para mí.
Si tiene dos
main.storyboards
y está realizando cambios en el incorrecto, esto puede suceder.
Esto puede suceder cada vez que conecte una salida de un
storyboard
desinstalado.
Tengo uno más ...
Si tiene una clase personalizada para un UITableViewCell pero olvida especificar Custom en el estilo de la celda.
Tuve el mismo problema después de copiar una clase (vinculada a un xib) para reutilizarla con otra clase de control de vista (vinculada a un guión gráfico). Olvidé eliminar
override var nibName
y
override var nibBundle
métodos
Después de eliminarlos, mis puntos de venta comenzaron a funcionar.
Tuve un problema similar cuando agregué previamente el registro (_: forCellReuseIdentifier :) para la celda personalizada después de haber definido el identificador en el guión gráfico. Tenía este código en la función viewDidLoad (). Una vez que lo quité, funcionó bien.
Veo que usas
ViewController
!
en la clase
ViewController
debe
usar
-viewDidLoad
,
no
-awakeFromNib
,
-awakeFromNib
para la clase
UIView
Verifique su conexión IBOutlet si está conectada al propietario del archivo o la vista. Podría haber errores.
Accidentalmente
subclasifiqué mi controlador de vista con
AVPlayerViewController
lugar de
UIViewController
.
Al reproducirlo en
UIViewController
cosas vuelven a la normalidad.
Esto debería ayudar.
Sin limpieza de compilación (normal y completa), eliminar carpetas de datos derivadas y salir de Xcode funcionó para mí.
Solución 100% funcional para crear ViewControllers desde XIB sin StoryBoards
- Crear clase CustomViewController: UIViewController
- Crear vista CustomViewControllerView.xib
- En CustomViewControllerView.xib en Interface Builder, seleccione Marcadores de posición -> Propietario del archivo
- En "Inspector de atributos" establezca Clase en CustomViewController
- En "Inspector de conexiones", conecte la "vista" a la vista de nivel superior de xib (asegúrese de que la clase de la vista de nivel superior no apunte a CustomViewController)
- En "Inspector de conexiones", conecte otras salidas (si es necesario / existe)
- Cree una instancia de CustomViewController en el controlador de vista principal / delegado de la aplicación
7.1.
// get/set outlets
controller.labelOutlet.text = "title"
controller.imageOutlet.image = UIImage(named: "image1")
7.2.
@IBOutlet private var containerView: UIView! // Connected to Storyboard
override open func loadView() {
containerView.addSubview(anotherView)
}
7.3.
@IBOutlet private var containerView: UIView!
override open func loadView() {
super.loadView()
containerView.addSubview(anotherView)
}