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

Pratik Bhiyani
fonte

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


E-Riddie
fonte
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.

Dave Wood
fonte
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)
}
Nick Yap
fonte
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.

MXV
fonte
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

Lance Samaria
fonte
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.

hasancan85
fonte
você também pode declarar sua propriedade como opcional via ?.
Julian B.