2012-09-21 30 views
36

Estoy usando el guión gráfico instantiateViewControllerWithIdentifier: y me doy cuenta de que todos los IBOutlets que he conectado todavía son nulos. Sin embargo, el IBActions he cableado el trabajo. La vista y el controlador están vinculados (es decir, controller.view no es nada), y si muestro la vista, se muestra lo que estoy esperando.storyboard instantiateViewControllerWithIdentifier no configura IBOutlets

¿Qué me estoy perdiendo?

Aquí está mi configuración:

  1. Tengo un controlador de vista definido en mi guión. Le he dado un identificador que es el mismo identificador que uso al invocar instantiateViewControllerWithIdentifier:
  2. He configurado el propietario de la vista haciendo clic en el Controlador de Vista (justo debajo del Servicio de Respuesta Inicial) y bajo el Inspector de Identidad establezco la Clase Personalizada el mismo nombre que la clase a la que quiero conectar la vista.
  3. Luego abro el editor asistente, y control arrastré los elementos de la interfaz de usuario para crear el IBOutlets y el IBActions.
+0

He intentado romper la vista en su propia punta y estoy viendo los mismos problemas. initWithNibName: bundle: tampoco parece establecer IBOutlets aunque se definan mediante ctrl-click-drag en IB. – BlueFish

+0

Como solución temporal, estoy usando [[NSBundle mainBundle] loadNibNamed: @ "myNib" owner: opciones de controlador: nil]. Esto carga el plumín y asigna las tuercas IB a los valores en el controlador. Pero esto parece incorrecto cuando hay un método en el controlador que parece que está haciendo lo mismo. – BlueFish

+0

Estoy un poco confundido con su configuración, ¿por qué está configurando el propietario de una vista? sus salidas de ib están ubicadas en un controlador de visualización en el tablero de la historia, ¿verdad? cuando crea una instancia de este controlador de vista, las salidas deberían funcionar si establece el tipo de este CV para que coincida con su encabezado e implementación personalizados. – Pochi

Respuesta

64

Parece que la vista se inicializa correctamente solo después de haberla accedido primero. El problema desaparece cuando se llama a

[self presentViewController:vc animated:NO completion:nil]; 

o más simplemente

[vc view]; 
+6

Esto es realmente extraño. Quiero decir, ¿sabes si esto es un comportamiento adecuado? Esto me había estado volviendo loco durante dos días hasta que encontré tu respuesta. – jere

+0

No estoy seguro de si esto es correcto, pero es comprensible. Por qué configurar una vista y todo simplemente porque se creó un controlador de vista. Uno podría suponer que quiere la vista cuando tiene el controlador de vista, pero quién sabe qué optimización llevó a este comportamiento.Sin embargo, debería estar documentado en algún lugar. –

+0

Esta solución funcionó para mí, gracias. – user1295558

0

salidas se establecen con Valor Codificación clave, se puede poner esto en su controlador de vista subclase:

- (void)setValue:(id)value forKeyPath:(NSString *)keyPath { 
    [super setValue:value forKeyPath:keyPath]; 
} 

- (void)setValue:(id)value forKey:(NSString *)key { 
    [super setValue:value forKeyPath:key]; 
} 

Y poner un punto de interrupción en las dos llamadas a súper.

En el depurador, que iba a tratar:

  1. Comparando 'sí' a la vista controlador cree que está aplicando a los puntos de venta. Quizás tu guión gráfico tenga un segundo controlador de vista que no estás esperando. Cuando dijiste que 'configuraste un dueño' pensé que era una terminología extraña. ¿Arrastró uno de los objetos del cubo para representar su controlador de vista además de la representación que ya está allí?

  2. Comparar [self valueForKey: key] o [self valueForKeyPath: keyPath] o simplemente [self outletName] con el valor pasado después de la llamada a super. Tal vez has establecido que no está haciendo lo que quieres. He visto un error como este aparecer un par de veces donde la gente tiene una salida para un objeto con un nombre como "firstName" y luego una acción con el selector "setFirstName:". Eso confunde la codificación del valor clave, y termina con setFirstName: se llama durante la carga de la punta con la intención de establecer la salida, pero el setter para la salida se implementa como un método de acción, por lo que nunca se establece la salida.

1

Ajuste de la trama para el ViewController instancia parece fijar los IBOutlets.

ejemplo:

DemoViewController *demoVC = [[self storyboard] instantiateViewControllerWithIdentifier:@"demoVC"]; 
demoVC.frame = self.view.frame; //or CGRectMake(0, 0, 1015, 604); 

Esto inicializar los IBOutlets de DemoViewController como Label, TextField, botón, etc. Tabla ,.

Espero que esto ayude.

+3

Está accediendo a la 'vista' ¿qué hace la magia, no establecer el' cuadro'. Se aplica a los puntos de venta que están dentro de la jerarquía de vistas (no, por ejemplo, los personalizados 'NSObject'). –

0

Si el objeto que está enlazando es una entidad de nivel superior en la escena, como un ArrayController, la referencia debe ser fuerte (¡no débil!) Ya que no es retenida por la jerarquía de vista. Una referencia débil puede causar un problema como el que describes.

Mira aquí para obtener más información: Should IBOutlets be strong or weak under ARC?

5

[me uso como mal ejemplo]

Tal vez no es una buena idea después de todo, funciona, pero viola la carga regular de hacer la aplicación inestable^_ ^.
Voy a dejar la respuesta aquí en caso de que alguien más quiera saber si lo haces.


que estaba teniendo el mismo problema, sin embargo, el componente personalizado diseñé no se carga a través presentViewController (carga en superposición a la vista anterior)

simplemente le puede llamar

myViewController.loadView()// Swift

[myViewController loadView] // Obj-C

+5

De los documentos: ** 'Nunca debe llamar a este método directamente. **. Primero copié ciegamente este código y mi vista se cargó, pero luego encontré otros problemas que no pude explicar. Después de eliminar este código, todo funcionó. Recomiendo encarecidamente no llamar a este método. – hashier

+0

Recomiendo no seguir el comentario anterior – Warrick

0

personas dieron solución de h Cómo cargar la vista cargada (algunas de las cuales nunca debe usar (loadView()) así que aquí hay una manera de verificar si su vista ya está cargada

Me encontré con el problema porque tenía una propiedad con un observador didSet para actualizar la interfaz de usuario que obviamente no funciona si no se establecen los puntos de venta, por lo que aquí es un código de ejemplo cómo trabajar alrededor de ella:

var name: String? { 
    didSet { 
     updateNameLabel() 
    } 
} 

override func viewDidLoad() { 
    super.viewDidLoad() 

    updateNameLabel() 
} 

func updateRoomLabel() { 
    guard isViewLoaded() else { 
     return 
    } 
    [...] 
} 

así que ahora cuando se visualizan los puntos de venta se actualizan sino también cada vez que actualice la propiedad

Cuestiones relacionadas