Error grave: uso del inicializador no implementado 'init (codificador :)' para la clase

157

Decidí continuar mi proyecto restante con Swift. Cuando agrego la clase personalizada (subclase de UIViewcontroller) a mi controlador de vista del guión gráfico y cargo el proyecto, la aplicación se bloquea repentinamente con el siguiente error:

error fatal: uso del inicializador no implementado 'init (codificador :)' para la clase

Este es un 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 sugiera algo

Pratik Bhiyani
fuente

Respuestas:

208

Problema

Esto es causado por la ausencia del inicializador init?(coder aDecoder: NSCoder)en el objetivo UIViewController. Ese método es obligatorio porque la instancia UIViewControllerde un UIStoryboarda lo llama.

Para ver cómo inicializamos un UIViewControllerde a UIStoryboard, eche un vistazo aquí

¿Por qué esto no es un problema con Objective-C?

Porque Objective-C hereda automáticamente todos los UIViewControllerinicializadores necesarios .

¿Por qué Swift no hereda automáticamente los inicializadores?

Swift por defecto no hereda los inicializadores debido a la seguridad. Pero heredará todos los inicializadores de la superclase si todas las propiedades tienen un valor (u opcional) y la subclase no ha definido ningún inicializador designado.


Solución

1. Primer método

Implementación manual init?(coder aDecoder: NSCoder)en el objetivoUIViewController

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

2. Segundo método

Eliminar init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: NSBundle?)en su objetivo UIViewControllerheredará todos los inicializadores necesarios de la superclase como Dave Wood señaló en su respuesta a continuación


E-Riddie
fuente
44
Gracias por esto. Seguimiento rápido ... Cuando crea el archivo TableViewController, Xcode ya incluye init(style: UITableViewStyle) { super.init(style: style) // Custom initialization } ¿Por qué podemos tener dos funciones de inicio? ¿Y alguna idea de por qué Apple no incluye el segundo init por defecto?
Trevor McKendrick
Esto no tiene nada que ver con iOS 7 o iOS 8. ¡Está conectado con la forma en que Swift hereda los inicializadores!
Sulthan
public init (view: UIViewController, frame: CGRect) {self.viewController = view self.imageName = "" self.actionName = "" super.init (frame: frame)}
scrainie 13/15
¡El primer método funcionó! ¡Mi tabla dinámica finalmente se llenó de celdas dinámicas! Todo porque la línea fatalError( "init(coder:) has not been implemented")detuvo mi aplicación.
Jose Manuel Abarca Rodríguez
26

Otra opción además de @ 3r1d es eliminar el siguiente método init de su clase:

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

Incluyendo ese método init, evita que la subclase herede la init(coder aDecoder: NSCoder!)de su superclase. Al no incluirlo, su clase heredará ambos.

Nota: Ver WWDC 2014 Sesión 403 "Intermedio Swift" en aproximadamente la marca 33:50 para más detalles.

Dave Wood
fuente
Gracias por señalar la explicación en la sesión 403. Pero si la clase secundaria solo tiene inicializadores de conveniencia, heredará los inicializadores de superclase, ¿verdad?
jamiltz
1
Si. Solo evita que los métodos init de superclase se hereden si proporciona sus propios métodos init designados (los que llaman superinits). Luego, debe especificar cuál de los superinits debe admitir agregándolos a su clase y simplemente llamando a la súper versión (como en la respuesta de @ 3r1d)
Dave Wood
Tener solo conveniencia init () sin (designado) init () en su clase secundaria causará un error de compilación. Esto se debe a que la función de conveniencia init () debe llamar a self.init () dentro de la definición de la función.
Ohmy, el
@narumolPug Eso es incorrecto. No necesita incluir initmétodos designados . Su clase hijo los heredará de la superclase. Todavía puede llamar, self.init()lo que ejecutará la super versión.
Dave Wood el
El momento exacto del video se puede encontrar aquí youtu.be/W1s9ZjDkSN0?t=2030
Honey
10

Para las personas que tienen el mismo problema con swift UICollectionViewCells, agregue el código que @ 3r1d sugirió a su UICollectionViewCellclase personalizada y no a View Controller:

init(coder aDecoder: NSCoder!)
{
    super.init(coder: aDecoder)
}
Nick Yap
fuente
¿A qué UICollectionViewCell te refieres? Init con el codificador es la forma de iniciar viewController
E-Riddie
No en este ejemplo, pero en caso de que alguien tenga un problema con él (lo hice) ... si intenta usar un UICollectionViewController, en el archivo .swift de su celda personalizada debe colocar init con el codificador.
Nick Yap
2
Debe
3

Para aquellos que necesitan el código en Swift:

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

[Editar] Esto fue para una versión anterior de Swift. Posiblemente ya no funcione.

MXV
fuente
3

Tuve este problema en una celda programática de collectionView y, a pesar de que el operador está preguntando sobre un vc, aún me encontré con esta pregunta cuando buscaba una respuesta. Para mí, el problema era que tenía

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

implementado por lo que la respuesta superior no funcionó. Lo que no tenía en la celda era el inicializador:

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

Una vez que lo agregué, el error desapareció

Lance Samaria
fuente
1

En lugar de agregar algunos métodos para hacer que el mecanismo interno funcione bien, iría definiendo mis atributos como @lazy e inicializándolos directamente en el alcance de la clase.

hasancan85
fuente
También puede declarar su propiedad como opcional a través de ?.
Julian B.