Erro fatal: uso do inicializador não implementado 'init (coder :)' para a classe


156

Decidi continuar meu projeto restante com a Swift. Quando adiciono a classe personalizada (subclasse de UIViewcontroller) ao meu controlador de exibição de storyboard e carrego o projeto, o aplicativo falha repentinamente com o seguinte erro:

erro fatal: uso do inicializador não implementado 'init (coder :)' para a classe

Este é um código:

import UIKit

class TestViewController: UIViewController {

    init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: NSBundle?) {
        super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
        // Custom initialization
    }

    override func viewDidLoad() {
        super.viewDidLoad()
              // Do any additional setup after loading the view.
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }

    /*
    // #pragma mark - Navigation

    // In a storyboard-based application, you will often want to do a little preparation before navigation
    override func prepareForSegue(segue: UIStoryboardSegue?, sender: AnyObject?) {
        // Get the new view controller using [segue destinationViewController].
        // Pass the selected object to the new view controller.
    }
    */
}

Por favor, sugira algo

Respostas:


207

Questão

Isso é causado pela ausência do inicializador init?(coder aDecoder: NSCoder)no destino UIViewController. Esse método é necessário porque a instanciação de a UIViewControllerde uma UIStoryboardchamada.

Para ver como inicializamos um UIViewControllerde a UIStoryboard, dê uma olhada aqui

Por que isso não é um problema com o Objective-C?

Porque o Objective-C herda automaticamente todos os UIViewControllerinicializadores necessários .

Por que o Swift não herda automaticamente os inicializadores?

Swift por padrão não herda os inicializadores devido à segurança. Mas herdará todos os inicializadores da superclasse se todas as propriedades tiverem um valor (ou opcional) e a subclasse não tiver definido nenhum inicializador designado.


Solução

1. Primeiro método

Implementando manualmente init?(coder aDecoder: NSCoder)no destinoUIViewController

required init?(coder aDecoder: NSCoder) {
    super.init(coder: aDecoder)
}

2. Segundo método

A remoção init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: NSBundle?)do seu alvo UIViewControllerherdará todos os inicializadores necessários da superclasse, como Dave Wood apontou em sua resposta abaixo



4
Obrigado por isso. Acompanhamento rápido ... Quando você cria o arquivo TableViewController, o Xcode já inclui init(style: UITableViewStyle) { super.init(style: style) // Custom initialization } Por que podemos ter duas funções init? E alguma idéia de por que a Apple não inclui o segundo init por padrão?
Trevor McKendrick 06/06

Isso não tem nada a ver com o iOS 7 ou o iOS 8. Isso está relacionado à maneira como o Swift herda os inicializadores!
precisa

Init pública (ver: UIViewController, quadro: CGRect) {self.viewController = vista self.imageName = "" self.actionName = "" super.init (quadro: Frame)}
scrainie

O primeiro método funcionou! Minha tabela dinâmica finalmente cheia de células dinâmicas !!! Tudo porque a linha fatalError( "init(coder:) has not been implemented")interrompeu meu aplicativo.
Jose Manuel Abarca Rodríguez 15/01

25

Outra opção além do @ 3r1d's é remover o seguinte método init da sua classe:

init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: NSBundle?) {
    super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
    // Custom initialization
}

A inclusão desse método init impede a subclasse de herdar a init(coder aDecoder: NSCoder!)superclasse. Ao não incluí-lo, sua classe herdará os dois.

Nota: Consulte a Sessão 403 da WWDC 2014 "Swift intermediário" na marca 33:50 para obter mais detalhes.


Obrigado por apontar a explicação na Sessão 403. Mas se a classe filho tiver apenas inicializadores de conveniência, ela herdará os inicializadores de superclasse, certo?
jamiltz

1
Sim. Você impede que os métodos init da superclasse sejam herdados se você fornecer seus próprios métodos init designados (aqueles que chamam super inits). Então você tem que especificar qual dos super inits ao apoio, adicionando-os à sua classe e apenas chamando a versão super (como na resposta de @ 3r1d)
Dave Madeira

Ter apenas a conveniência init () sem (designado) init () na sua classe filho causará erro de compilação. Isso porque a função init () de conveniência deve chamar self.init () dentro da definição da função.
Ohmy

@narumolPug Isso está incorreto. Você não precisa incluir initmétodos designados . Sua classe filho os herdará da super classe. Você ainda pode ligar self.init()para executar a super versão.
Dave Madeira

O momento exato do vídeo pode ser encontrado aqui youtu.be/W1s9ZjDkSN0?t=2030
Honey

10

Para pessoas com o mesmo problema com o swift UICollectionViewCells, adicione o código que @ 3r1d sugeriu à sua UICollectionViewCellclasse personalizada e não ao View Controller:

init(coder aDecoder: NSCoder!)
{
    super.init(coder: aDecoder)
}

a que UICollectionViewCell você está se referindo? Init com codificador é o caminho para inicializar o viewController
E-Riddie

Não neste exemplo, mas no caso de alguém ter um problema com ele (eu fiz) ... se você tentar usar um UICollectionViewController, no seu arquivo .swift da célula personalizada, será necessário colocar o init no codificador.
perfil completo de Nick Yap

2
Você precisa adicionar esse código sempre que usar essa maneira de instanciação stackoverflow.com/questions/24035984/…
E-Riddie

3

Para aqueles que precisam do código no Swift:

required init(coder aDecoder: NSCoder) {
    super.init(coder: aDecoder)
}

[Editar] Isto foi para uma versão mais antiga do Swift. Possivelmente não funciona mais.


3

Eu tive esse problema em uma célula programática collectionView e, mesmo que o op esteja perguntando sobre um vc, eu ainda entrei nessa questão ao procurar uma resposta. Para mim, a questão era que eu tinha

required init?(coder aDecoder: NSCoder) {
    fatalError("init(coder:) has not been implemented")
}

implementado para que a resposta principal não funcionasse. O que eu não tinha na célula era o inicializador:

// my programmatic cell was missing this
override init(frame: CGRect) {
    super.init(frame: frame)
}

Depois que eu adicionei, o erro foi embora


1

Em vez de adicionar alguns métodos para fazer o mecanismo interno funcionar bem, eu definiria meus atributos como @lazy e os inicializaria no escopo da classe.


você também pode declarar sua propriedade como opcional via ?.
Julian B.
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.