Errore irreversibile: utilizzo dell'inizializzatore non implementato 'init (coder :)' per la classe


157

Ho deciso di continuare il mio progetto rimanente con Swift. Quando aggiungo la classe personalizzata (sottoclasse di UIViewcontroller) al mio controller di visualizzazione dello storyboard e carico il progetto, l'app si blocca improvvisamente con il seguente errore:

errore fatale: utilizzo dell'inizializzatore non implementato 'init (coder :)' per la classe

Questo è un codice:

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.
    }
    */
}

Per favore, suggerisci qualcosa

Risposte:


208

Problema

Ciò è causato dall'assenza dell'inizializzatore init?(coder aDecoder: NSCoder)sulla destinazione UIViewController. Tale metodo è necessario perché l'istanza di a UIViewControllerda una lo UIStoryboardchiama.

Per vedere come inizializziamo una UIViewControllerda una UIStoryboard, dai un'occhiata qui

Perché questo non è un problema con Objective-C?

Perché Objective-C eredita automaticamente tutti gli UIViewControllerinizializzatori richiesti .

Perché Swift non eredita automaticamente gli inizializzatori?

Swift per impostazione predefinita non eredita gli inizializzatori a causa della sicurezza. Ma erediterà tutti gli inizializzatori dalla superclasse se tutte le proprietà hanno un valore (o facoltativo) e la sottoclasse non ha definito alcun inizializzatore designato.


Soluzione

1. Primo metodo

Implementazione manuale init?(coder aDecoder: NSCoder)sull'obiettivoUIViewController

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

2. Secondo metodo

La rimozione init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: NSBundle?)sul bersaglio UIViewControllererediterà tutti gli inizializzatori richiesti dalla superclasse mentre Dave Wood indicava la sua risposta di seguito



4
Grazie per questo. Follow-up rapido ... Quando si crea il file TableViewController, Xcode include già init(style: UITableViewStyle) { super.init(style: style) // Custom initialization } Perché possiamo avere due funzioni init? E qualche idea sul perché Apple non includa il secondo init per impostazione predefinita?
Trevor McKendrick,

Questo non ha nulla a che fare con iOS 7 o iOS 8. Questo è collegato al modo in cui Swift eredita gli inizializzatori!
Sulthan,

public init (view: UIViewController, frame: CGRect) {self.viewController = view self.imageName = "" self.actionName = "" super.init (frame: frame)}
scrainie

Il primo metodo ha funzionato! La mia tabella dinamica è finalmente piena di celle dinamiche !!! Tutto perché la linea ha fatalError( "init(coder:) has not been implemented")bloccato la mia app.
Jose Manuel Abarca Rodríguez,

26

Un'altra opzione oltre a quella di @ 3r1d è quella di rimuovere il seguente metodo init dalla tua classe:

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

Includendo quel metodo init, impedisce alla sottoclasse di ereditare la init(coder aDecoder: NSCoder!)dalla sua superclasse. Non includendolo, la tua classe erediterà entrambi.

Nota: vedi Sessione 403 del WWDC 2014 "Intermediate Swift" a circa il segno 33:50 per maggiori dettagli.


Grazie per aver sottolineato la spiegazione sulla Sessione 403. Ma se la classe figlio ha solo inizializzatori di convenienza, erediterà gli inizializzatori di superclasse giusto?
Jamiltz,

1
Sì. Impedisci che i metodi init super class vengano ereditati solo se fornisci i tuoi metodi init designati (quelli che chiamano superinit). Quindi devi specificare quali dei superinit supportano aggiungendoli alla tua classe e chiamando semplicemente la versione super (come nella risposta di @ 3r1d)
Dave Wood,

Avere solo convenienza init () senza (designato) init () nella classe figlio provocherà un errore di compilazione. Questo perché la funzione conveni (init) deve chiamare self.init () all'interno della definizione della funzione.
Ohmy,

@narumolPug È errato. Non è necessario includere initmetodi designati . La tua classe figlio li erediterà dalla super classe. Puoi ancora chiamare self.init()che eseguirà la versione super.
Dave Wood,

Il momento esatto del video può essere trovato qui youtu.be/W1s9ZjDkSN0?t=2030
Honey

10

Per le persone che hanno lo stesso problema con swift UICollectionViewCells, aggiungi il codice suggerito da @ 3r1d alla tua UICollectionViewCellclasse personalizzata e non al View Controller:

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

a quale UICollectionViewCell ti riferisci? Init con coder è il modo per avviare viewController
E-Riddie il

Non in questo esempio, ma nel caso in cui qualcuno abbia un problema (l'ho fatto) ... se si tenta di utilizzare un UICollectionViewController, nel file .swift della cella personalizzata è necessario inserire init con coder.
Nick Yap,

2
È necessario aggiungere questo ogni volta che si utilizza il codice in questo modo di esemplificazione stackoverflow.com/questions/24035984/...
E-Riddie

3

Per coloro che necessitano del codice in Swift:

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

[Modifica] Questo era per una versione precedente di Swift. Forse non funziona più.


3

Ho avuto questo problema in una cella collectionView programmatica e anche se l'op sta chiedendo un vc, sono ancora arrivato a questa domanda durante la ricerca di una risposta. Per me il problema era che avevo

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

implementato in modo che la risposta migliore non funzionasse. Quello che non avevo nella cella era l'inizializzatore:

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

Una volta aggiunto, l'errore è scomparso


1

Invece di aggiungere alcuni metodi per far funzionare bene il meccanismo interno, vorrei definire i miei attributi come @lazy e inizializzarli proprio nell'ambito della classe.


puoi anche dichiarare la tua proprietà come facoltativa tramite ?.
Julian B.
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.