Pergunta

Eu tenho uma subclasse UITableViewController que é instanciado, dependendo de onde ele é usado, em um NIB ou via código. Em ambos os casos eu quero fazer personalização no método de inicialização. Será que isso significa necessariamente que implementar ambos initWithNibName:bundle: e initWithCoder:, e que cada método chamar seu respectivo initializer super?

Enquanto eu não preciso disso agora, e se eu também quero ser capaz de criar uma instância do controlador de vista com initWithStyle:? Será que eu, em seguida, precisa de 3 métodos de inicialização diferentes que reproduzem o mesmo comportamento?

Parece que isso viola o conjunto designado initializer convenção, como não seria essencialmente 3 initializers separados que não acabam chamando um método init comum. Ou há uma maneira de criar um comum designada initializer apoiando os 3 diferentes rotas instanciar?

Foi útil?

Solução

A minha confusão foi baseada na crença equivocada de que cada classe deve ter um único inicializador designado. Isso não é verdade, e no caso de UITableViewController há 3 inicializadores designados (tanto quanto eu posso dizer):

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

Você precisa substituir 1 ou mais destes em sua subclasse dependendo de como sua subclasse é instanciado. No meu caso eu tive que implementar # 2 e # 3 já que a classe pode ser carregado a partir de um NIB, ou instanciado via código com referência a um NIB. (Imagino que é raro que você vai usar tanto initWithStyle: e initWithNibName:bundle: para uma única classe.)

Eu encontrei da Apple Codificação Diretrizes para Cocoa útil.

Outras dicas

Internamente,

  • -initWithStyle: de UITableViewController chama -init do Super seguida, defina o ivar _tableViewStyle.
  • -init de UIViewController simplesmente chama -initWithNibName:bundle: com argumentos padrão.
  • UITableViewController não override -initWithNibName:bundle:.

Portanto, se você substituir -initWithNibName:bundle: então -initWithStyle: vai adotar a mudança também. Claro que, para jogar pelo seguro (como você não deve confiar em detalhes de implementação), substituir os dois.

(E não há necessidade de -initWithCoder: substituição a menos que você vai un / arquivar os casos.)

Para esclarecer, initWithStyle:, sendo UITableViewController está só publicou initializer nos docs, é seu único explícita inicializador designado.

initWithNibName:bundle: é herdada de UIViewController e é o designado initializer para essa classe. Como tal, de acordo com as diretrizes de cacau, UITableViewController deve substituir esse método (por implementá-lo). No entanto, isso não torná-lo um designado initializer de UITableViewController.

initWithCoder: é, como você aponta, um implícito designado initializer de NSCoding.

Implementar:

- (void) viewDidLoad

e fazer a sua inicialização do componente lá.

Tem a vantagem de só fazer a inicialização quando a vista é realmente solicitado.

Ou apenas fazer um método de configuração separado invocado por todos os inicializadores.

Uma adição aos postos acima que -initWithCoder referência:

Se você adicionou acrescentou o controlador de vista a seu pai via construtor de interface (por exemplo: se o controlador de exibição está ligado a um controlador de barra de abas no construtor de interface)., Em seguida, você precisará substituir -initWithCoder

(-. InitWithNibName só será chamado quando você cria o controlador de vista de programação)

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top