Erreur fatale: utilisation de l'initialiseur non implémenté 'init (coder :)' pour la classe

157

J'ai décidé de continuer mon projet restant avec Swift. Lorsque j'ajoute la classe personnalisée (sous-classe de UIViewcontroller) à mon contrôleur de vue storyboard et charge le projet, l'application se bloque soudainement avec l'erreur suivante:

erreur fatale: utilisation de l'initialiseur non implémenté 'init (coder :)' pour la classe

Ceci est un code:

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

Veuillez suggérer quelque chose

Pratik Bhiyani
la source

Réponses:

208

Problème

Cela est dû à l'absence de l'initialiseur init?(coder aDecoder: NSCoder)sur la cible UIViewController. Cette méthode est requise car l'instanciation d'un à UIViewControllerpartir d'un l' UIStoryboardappelle.

Pour voir comment nous initialisons un à UIViewControllerpartir de a UIStoryboard, veuillez jeter un œil ici

Pourquoi n'est-ce pas un problème avec Objective-C?

Parce que Objective-C hérite automatiquement de tous les UIViewControllerinitialiseurs requis .

Pourquoi Swift n'hérite-t-il pas automatiquement des initialiseurs?

Swift par défaut n'hérite pas des initialiseurs pour des raisons de sécurité. Mais il héritera de tous les initialiseurs de la superclasse si toutes les propriétés ont une valeur (ou facultative) et que la sous-classe n'a défini aucun initialiseur désigné.


Solution

1. Première méthode

Mise en œuvre manuelle init?(coder aDecoder: NSCoder)sur la cibleUIViewController

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

2. Deuxième méthode

Le retrait init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: NSBundle?)de votre cible UIViewControllerhéritera de tous les initialiseurs requis de la superclasse comme Dave Wood l'a souligné dans sa réponse ci-dessous


E-Riddie
la source
4
Merci pour cela. Suivi rapide ... Lorsque vous créez le fichier TableViewController, Xcode inclut déjà init(style: UITableViewStyle) { super.init(style: style) // Custom initialization } Pourquoi pouvons-nous avoir deux fonctions init? Et une idée de la raison pour laquelle Apple n'inclut pas le 2ème init par défaut?
Trevor McKendrick
Cela n'a rien à voir avec iOS 7 ou iOS 8. Cela est lié à la façon dont Swift hérite des initiateurs!
Sulthan
public init (vue: UIViewController, frame: CGRect) {self.viewController = view self.imageName = "" self.actionName = "" super.init (frame: frame)}
scrainie
La première méthode a fonctionné! Ma table dynamique s'est enfin remplie de cellules dynamiques !!! Tout cela parce que la ligne a fatalError( "init(coder:) has not been implemented")arrêté mon application.
Jose Manuel Abarca Rodríguez
26

Une autre option en plus de @ 3r1d est de supprimer la méthode init suivante de votre classe:

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

L'inclusion de cette méthode init empêche la sous-classe d'hériter init(coder aDecoder: NSCoder!)de sa super classe. En ne l'incluant pas, votre classe héritera des deux.

Remarque: Voir WWDC 2014 Session 403 «Intermediate Swift» à environ 33:50 pour plus de détails.

Dave Wood
la source
Merci d'avoir indiqué l'explication sur la session 403. Mais si la classe enfant n'a que des initialiseurs de commodité, elle héritera des initialiseurs de super classe, n'est-ce pas?
jamiltz
1
Oui. Vous n'empêchez l'héritage des méthodes d'initialisation de la super classe que si vous fournissez vos propres méthodes d'initialisation désignées (celles qui appellent des super inits). Ensuite, vous devez spécifier lequel des super-inits prendre en charge en les ajoutant à votre classe et en appelant simplement la super version (comme dans la réponse de @ 3r1d)
Dave Wood
Avoir seulement la convenance init () sans (désigné) init () dans votre classe enfant provoquera une erreur de compilation. C'est parce que la fonction de commodité init () doit appeler self.init () dans la définition de fonction.
Ohmy
@narumolPug C'est incorrect. Vous n'avez pas besoin d'inclure des initméthodes désignées . Votre classe enfant les héritera de la super classe. Vous pouvez toujours appeler self.init()qui exécutera la super version.
Dave Wood
Le moment exact de la vidéo peut être trouvé ici youtu.be/W1s9ZjDkSN0?t=2030
Honey
10

Pour les personnes ayant le même problème avec swift UICollectionViewCells, ajoutez le code que @ 3r1d a suggéré à votre UICollectionViewCellclasse personnalisée et non au contrôleur de vue:

init(coder aDecoder: NSCoder!)
{
    super.init(coder: aDecoder)
}
Nick Yap
la source
de quel UICollectionViewCell parlez-vous? Init avec codeur est le moyen d'initier le viewController
E-Riddie
Pas dans cet exemple, mais au cas où quelqu'un aurait un problème avec lui (je l'ai fait) ... si vous essayez d'utiliser un UICollectionViewController, dans votre fichier .swift de cellule personnalisée, vous devez mettre init avec le codeur.
Nick Yap
2
Vous devez ajouter ce code à chaque fois que vous utilisez cette méthode d'instanciation stackoverflow.com/questions/24035984/...
E-Riddie
3

Pour ceux qui ont besoin du code dans Swift:

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

[Modifier] C'était pour une ancienne version de Swift. Peut-être ne fonctionne plus.

MXV
la source
3

J'ai eu ce problème dans une cellule de collectionView programmatique et même si l'opération pose des questions sur un vc, j'ai toujours atterri sur cette question lors de la recherche d'une réponse. Pour moi, le problème était que j'avais

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

mis en œuvre pour que la réponse principale ne fonctionne pas. Ce que je n'avais pas dans la cellule était l'initialiseur:

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

Une fois que je l'ai ajouté, l'erreur est partie

Lance Samaria
la source
1

Plutôt que d'ajouter des méthodes pour que le mécanisme interne fonctionne correctement, je choisirais de définir mes attributs comme @lazy et de les initialiser directement dans la portée de la classe.

hasancan85
la source
vous pouvez également déclarer votre propriété comme facultative via ?.
Julian B.