Estou aprendendo o desenvolvimento para iOS em um curso online e sempre que faço uma visualização personalizada (célula de visualização de tabela customizada, célula de visualização de coleção, etc.) o instrutor sempre implementa este inicializador:
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
Por que exatamente eu sempre tenho que ligar assim? O que isso faz? Posso colocar propriedades dentro do init?
NSCoding
, será necessário implementar esse inicializador, já que ele é necessário para as classes que o implementamNSCoding
. Você deve pelo menos chamar o método init da superclasse. Se oNSCoder
contém propriedades codificadas para sua classe, você pode usar este método para recuperá-lasRespostas:
Vou começar esta resposta na direção oposta: e se você quiser salvar o estado de sua visualização em disco? Isso é conhecido como serialização . O reverso é a desserialização - restaurando o estado do objeto do disco.
O
NSCoding
protocolo define dois métodos para serializar e desserializar objetos:Então, por que isso é necessário em sua classe personalizada? A resposta é Interface Builder. Quando você arrasta um objeto para um storyboard e o configura, o Interface Builder serializa o estado desse objeto no disco e o desserializa quando o storyboard aparece na tela. Você precisa dizer ao Interface Builder como fazer isso. No mínimo, se você não adicionar nenhuma propriedade nova à sua subclasse, você pode simplesmente pedir à superclasse para fazer o empacotamento e descompactação para você, daí a
super.init(coder: aDecoder)
chamada. Se sua subclasse for mais complexa, você precisará adicionar seu próprio código de serialização e desserialização para a subclasse.Isso contrasta com a abordagem do Visual Studio, que é escrever código em um arquivo oculto para criar o objeto em tempo de execução.
fonte
init(coder aCoder : NSCoder)
?awakeFromNib
não funcionará.awakeFromNib
é invocado em tempo de execução . Tudo o que você faz no Interface Builder é durante o tempo de design . Para transportar o que você fez em tempo de design para tempo de execução éencodeWithCoder
(economia) einit(coder:)
(carregamento)awakeFromNib
ouinitWIthFrame
O requisito para implementar esse inicializador é uma consequência de duas coisas:
O princípio da substituição de Liskov . Se S é uma subclasse de T (por exemplo,
MyViewController
é uma subclasse deViewController
), então os objetos S (instâncias deMyViewController
) devem ser substituídos em onde T objetos (instâncias deViewController
) são esperados.Os inicializadores não são herdados em Swift se algum inicializador for explicitamente definido na subclasse. Se um inicializador for fornecido explicitamente, todos os outros deverão ser fornecidos explicitamente (que podem então apenas chamar
super.init(...)
). Veja esta questão para justificativa. Está em Java, mas ainda se aplica.No ponto 1, tudo o que o original
ViewController
pode fazer, aMyViewController
subclasse deve ser capaz de fazer. Uma dessas coisas é poder ser inicializado a partir de um dadoNSCoder
. No ponto 2, suaMyViewController
subclasse não herda automaticamente essa habilidade. Portanto, você deve fornecer manualmente o inicializador que atenda a esse requisito. Nesse caso, você só precisa delegar para a superclasse, para que ela faça o que normalmente faria.fonte