2010-01-14 14 views
5

Estoy abriendo una nueva pregunta para el seguimiento de mi última (superview and parentviewcontroller nil after adding a subview). Básicamente entiendo que usar subvistas es una buena idea, pero que no debería tener un ViewController que controle una subvista que viva dentro de otro ViewController. Básicamente me gustaría hacer lo siguiente ... Tengo dos ViewControllers que comparten una subvista común. Creé esa subvista como una punta llamada SearchDate.xib. El propietario del archivo es una clase correspondiente SearchDateView.m/h. Esa clase tiene una salida para el único elemento dentro de UIView en el plumín, que es una etiqueta. La clase SearchDateView también tiene una función para cambiar el valor de la etiqueta en SearchDateView.xib. Me gustaría que mis ViewControllers carguen esta plumilla, pero aparentemente no tengo idea de cómo cargar correctamente la plumilla. No importa lo que haga, en el mejor de los casos, no se muestra nada y, en el peor, se lanza una excepción. Los Apple Docs hablan de arrastrar en otras instancias de clases en IB directamente a su vista principal, pero parece que no funciona. Tengo una toma SearchDateView en mi ViewController y he intentado hacer esto en vista de la carga del controlador:¿Cómo puedo crear un plumín con una clase de vista asociada que pueda ser utilizado por múltiples ViewControllers?

searchDateView = [[[NSBundle mainBundle] loadNibNamed:@"SearchDateView" owner:self options:nil] objectAtIndex:0]; 
[[self view] addSubview:searchDateView]; 

Pero consigo esta excepción:

*** Terminating app due to uncaught exception 'NSUnknownKeyException', reason: '[<MainViewController 0x431fac0> setValue:forUndefinedKey:]: this class is not key value coding-compliant for the key searchDateLabel.' 

Yo sé que estoy haciendo algo totalmente equivocado, pero lo ¿Es la forma correcta de tener un plumín, una clase de vista asociada que actualiza algunos de los objetos en ese plumín y reutilizar ese plumín en diferentes controladores?

EDIT: Dado el comentario, quizás esto no fue lo suficientemente claro. No quiero usar el mismo archivo de punta para una vista ENTERA, sino una subvista. Entonces, por ejemplo, el controlador A tiene un mapa y también un SearchDateView, y el controlador B tiene una vista de tabla y un SearchDateView. Así que me pregunto cómo cargar una subvista en múltiples controladores ...

Respuesta

2

No debería haber ningún problema al usar el mismo archivo NIB para múltiples controladores cuando cada uno se inicializa usando initWithNibName: paquete :. Sin embargo, normalmente no carga el propio archivo de punta del controlador desde el controlador.

Si carga un archivo nib utilizando loadNibNamed ::: entonces obtiene un NSArray con los objetos definidos en él, por lo que no puede usarlo como una vista directamente. Una forma de obtener una vista es buscar a través de la matriz usando for() o algo para encontrar el objeto que desea, pero si establece owner: self, entonces debe conectarse a las tomas conectadas al propietario de File en Self como propietario de File's self . Pero puede descartar el valor de retorno en este caso; no necesitas la matriz devuelta. Ese puede ser tu problema principal (golpear la salida con la matriz) si tienes esa toma de corriente conectada.

Es posible usar loadNibNamed para cargar un objeto de vista específico (asumiendo que lo elijas de la matriz devuelta), luego mostrarlo de alguna manera, pero generalmente es más fácil usar initWithNibName en el controlador (en cuyo caso el Propietario del archivo ser el controlador).

Ah, y también puede establecer el archivo de punta para un controlador en el Interface Builder. No debería haber un problema con el uso del mismo plumín para múltiples controladores, ya que esencialmente le estarías diciendo a Interface Builder que configure el archivo nib para hacer algo como initWithNibNamed. Haga clic en el objeto del controlador y verifique la ventana del inspector.

actualización

probablemente haría esto con el fin de utilizar solamente un punto de vista en varios controladores:

NSArray *nib = [[NSBundle mainBundle] loadNibNamed:@"FooView" 
               owner:self options:nil]; 
    for (id obj in nib) 
     if ([obj isKindOfClass:[FooView class]]) 
      myNewView = (FooView *)obj; 

(robado del Capítulo 8: Células 2 en el código de ejemplo de Principio iPhone 3 Development.)

Puedes hacer esto con outlets en IB, en cuyo caso puedes omitir el bucle for, pero es probable que necesites una superclase para ambos controladores que declaran la salida, y algo para decirle a Interface Builder que File's Owner es una instancia de esa superclase para que sepa sobre la salida. Probablemente no valga la pena.

+0

Lo siento, quizás no estaba demasiado claro. No quiero usar el mismo archivo de punta para una vista ENTERA, sino una subvista. Entonces, por ejemplo, el controlador A tiene un mapa y también un SearchDateView, y el controlador B tiene una vista de tabla y un SearchDateView. Así que me pregunto cómo cargar una subvista en múltiples controladores. – deadroxy

+0

Actualicé mi respuesta para ser más específico a su situación. – Nimrod

+0

Sí, la superclase parece ser la única solución "real" para mi problema. Probablemente volveré a refactorizar más tarde, pero por ahora he encontrado algunas soluciones, ¡gracias! – deadroxy

0

que tienen una toma de SearchDateView en mi ViewController y he intentado hacer esto en vista de la carga del controlador:

searchDateView = [[[NSBundle mainBundle] loadNibNamed:@"SearchDateView" owner:self options:nil] objectAtIndex:0]; 
[[self view] addSubview:searchDateView]; 

pero me da esta excepción:

*** Terminating app due to uncaught exception 'NSUnknownKeyException', reason: '[<MainViewController 0x431fac0> setValue:forUndefinedKey:]: this class is not key value coding-compliant for the key searchDateLabel.' 

En ausencia de Cocoa Bindings (que solo está disponible en Cocoa, no en Cocoa Touch), no creo que estos dos estén relacionados.

En Xcode, agregue un punto de interrupción simbólico en objc_exception_throw, luego ejecute su aplicación en el depurador. Cuando se rompe, mira en la pila de llamadas. Podrá encontrar dónde se originó realmente el problema.

Cuestiones relacionadas