2009-04-13 9 views
16

Tengo una subclase UITableViewController que se crea una instancia, dependiendo de dónde se utiliza, en un NIB o mediante un código. En ambos casos, quiero hacer personalización en el método de inicialización. ¿Significa eso que necesito implementar initWithNibName:bundle:yinitWithCoder:, y cada método llamaría a su superinicializador?Qué inicializador (s) anular para la subclase UITableViewController

Si bien no necesito esto ahora, ¿qué sucede si también quiero poder crear una instancia del controlador de vista con initWithStyle:? ¿Necesitaría entonces 3 métodos de inicio diferentes que reproduzcan el mismo comportamiento?

Parece que esto viola toda la convención de inicializador designada, ya que básicamente habría 3 inicializadores separados que no terminan llamando a un método init común. ¿O hay una forma de crear un inicializador designado común mientras se soportan las 3 rutas de creación de instancias diferentes?

Respuesta

11

Mi confusión se basa en la creencia errónea de que cada clase debe tener un único inicializador designado. Esto no es cierto, y en el caso de UITableViewController hay 3 inicializadores designados (por lo que puedo decir):

  1. initWithStyle: declarado localmente
  2. initWithNibName:bundle: heredado de UIViewController
  3. initWithCoder: de adoptar NSCoding protocolo

necesita anular 1 o más de estos en su subclase dependiendo de cómo se crea una instancia de su subclase. En mi caso, tuve que implementar # 2 y # 3, ya que la clase puede cargarse desde un NIB, o crear una instancia a través de un código con referencia a un NIB. (Me imagino que es raro que se va a utilizar tanto initWithStyle: y initWithNibName:bundle: para una sola clase.)

me encontré de Apple Coding Guidelines for Cocoa útil.

+0

Eso no es exacto. - [UIViewController initWithCoder:] parece invocar - [UIViewController initWithNibName: bundle:]. No hay necesidad de anularlo. Sigue los consejos de KennyTM. – fnf

+0

es exacto. Tengo una situación donde solo se invoca initWithCoder. (Tengo todos los 3 métodos anulados). – Sam

+0

Lo que realmente confunde en iOS8 es que initWithStyle: llama a initWithNibName: bundle: y ambos tienen que declararse como inicializadores designados. Esto no se ajusta a las reglas rápidas de inicialización. En iOS8, si no define initWithNibName: bundle: y llama a initWithStyle :, la aplicación se bloquea. Esto ha sido arreglado en iOS9. –

0

implementar:

- (void) viewDidLoad 

y hacer su inicialización componente allí.

Tiene la ventaja de solo hacer la inicialización cuando la vista es realmente solicitada.

O simplemente haga un método de instalación separado invocado por todos los inicializadores.

+0

No puedo usar viewDidLoad porque, en concreto, necesito configurar self.navigationItem que puede ser utilizado antes de la vista es cargado . Podría hacer un método de configuración diferente. Entonces, ¿es simplemente que NSCoding es fundamentalmente una excepción a la regla del "inicializador designado único"? –

2

Para aclarar, initWithStyle:, siendo UITableViewController el único inicializador publicado en los documentos, es un inicializador designado explícitamente.

initWithNibName:bundle: se hereda de UIViewController y es el inicializador designado para esa clase. Como tal, de acuerdo con las directrices de Cocoa, UITableViewControllerdebe anular este método (implementándolo). Sin embargo, esto no lo convierte en un inicializador designado de UITableViewController.

initWithCoder: es, como usted señala, un inicializador designado implícito de NSCoding.

7

Internamente,

  • de UITableViewController -initWithStyle: llama a la super -init continuación, establezca la Ivar _tableViewStyle.
  • El -init de UIViewController simplemente llama a -initWithNibName:bundle: con argumentos predeterminados.
  • UITableViewController no anula -initWithNibName:bundle:.

Por lo tanto, si reemplaza -initWithNibName:bundle: entonces -initWithStyle: adoptará el cambio también. Por supuesto, para jugar seguro (ya que no debe confiar en los detalles de implementación), anule ambos.

(Y no hay necesidad de anular -initWithCoder: a menos que se ONU/archivar los casos.)

+0

Reemplazando -initWithNibName: bundle: por sí solo debería ser seguro, porque no es realmente un detalle de implementación, sino un aspecto del marco que los inicializadores designados se llaman en toda la cadena de herencia. Y esa cadena de herencia en sí es parte de la interfaz de UITableViewController. – TBBle

0

Una adición a los puestos de arriba que -initWithCoder referencia:

si se ha añadido añadido el controlador de vista de su matriz a través del constructor de interfaz (por ejemplo: si el controlador de vista está conectado a un controlador de barra de pestañas en el constructor de interfaz), entonces necesita anular -iniciar ConCoder.

(-initWithNibName sólo se llama cuando se crea el controlador de vista mediante programación.)

Cuestiones relacionadas