La classe n'a pas d'initialiseur Swift

183

J'ai un problème avec la classe Swift. J'ai un fichier rapide pour la classe UITableViewController et la classe UITableViewCell. Mon problème est la classe UITableViewCell et les points de vente. Cette classe a une erreur. La classe "HomeCell" n'a pas d'initialiseurs et je ne comprends pas ce problème.

Merci pour vos réponses.

import Foundation
import UIKit

class HomeTable: UITableViewController, UITableViewDataSource, UITableViewDelegate {

    @IBOutlet var tableViex: UITableView!

    var items: [(String, String, String)] = [
        ("Test", "123", "1.jpeg"),
        ("Test2", "236", "2.jpeg"),
        ("Test3", "678", "3.jpeg")
    ]

    override func viewDidLoad() {
        super.viewDidLoad()

        var nib = UINib(nibName: "HomeCell", bundle: nil)
        tableView.registerNib(nib, forCellReuseIdentifier: "bookCell")
    }

    // Number row
    override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return self.items.count
    }

    // Style Cell
    override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {

        var cell:UITableViewCell = self.tableView.dequeueReusableCellWithIdentifier("bookCell") as UITableViewCell

        // Style here

        return cell

    }

    // Select row
    override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
        // Select
    }

}

// PROBLEM HERE
class HomeCell : UITableViewCell {

    @IBOutlet var imgBook: UIImageView
    @IBOutlet var titleBook: UILabel
    @IBOutlet var pageBook: UILabel

    func loadItem(#title: String, page: String, image:String) {
        titleBook.text = title
        pageBook.text = page
        imgBook.image = UIImage(named: image)
    }

}
Kevin Py
la source
Avez-vous besoin d'indiquer explicitement le type de la variable nib comme UINib facultatif?
Cocoadelica

Réponses:

257

Vous devez utiliser des options implicitement déroulées pour que Swift puisse faire face aux dépendances circulaires (parent <-> enfant des composants de l'interface utilisateur dans ce cas) pendant la phase d'initialisation.

@IBOutlet var imgBook: UIImageView!
@IBOutlet var titleBook: UILabel!
@IBOutlet var pageBook: UILabel!

Lisez ce document , ils expliquent tout bien.

mprivat
la source
21
Votre explication et ce document ont tous un sens pour moi, mais pas le message d'erreur!
coco
4
C'est probablement une question pour Apple
mprivat
Les @IBOutlets doivent également être marqués comme faibles afin d'éviter le cycle de rétention.
Dennis Pashkov le
@Dennis Pashkov Autant que je sache, ce n'est que pour IBOutlets qui est dans la hiérarchie des vues de viewController. Sinon, il sera libéré immédiatement parce que personne ne le détiendra.
Alston
3
J'ai eu ce problème où j'ai défini un Bool en utilisant var myBool: Bool.
jungledev
96

Solution rapide - assurez-vous que toutes les variables qui ne sont pas initialisées lors de leur création (par exemple var num : Int?vs var num = 5) ont un ?ou !.

Réponse longue (recommandée) - lisez la documentation comme le suggère mprivat ...

Byron Coetsee
la source
Pour résoudre cette erreur, vous devez configurer la valeur par défaut pour? variables, par exemple: laissez showUserPointViewDelegate: ShowUserPointsViewControllerControl? = nil
Vladimir Vodolazkiy
+1 ?signifie qu'il peut être nul, mais si c'était le cas, il n'y a aucun problème à avancer et à ne rien faire. !signifie que si, après le déballage, il était nul, alors un crash - les deux satisfont à l'exigence d'initiation - en informant le compilateur: je sais / je veux qu'il démarre sous la forme nil.
Honey
Recherchez varet letdans vous affichez le contrôleur, et recherchez les !s et ?s manquants
Wiingaard
33

Ceci est de Apple doc

Les classes et les structures doivent définir toutes leurs propriétés stockées sur une valeur initiale appropriée au moment où une instance de cette classe ou structure est créée. Les propriétés stockées ne peuvent pas être laissées dans un état indéterminé.

Vous obtenez le message d'erreur La classe "HomeCell" n'a aucun initialiseur car vos variables sont dans un état indéterminé. Soit vous créez des initialiseurs, soit vous en faites des types facultatifs, en utilisant! ou ?

CodeHelp
la source
32

Ma réponse concerne l'erreur en général et non le code exact de l'OP. Aucune réponse n'a mentionné cette note, alors j'ai simplement pensé l'ajouter.

Le code ci-dessous générerait également la même erreur:

class Actor {
    let agent : String? // BAD! // Its value is set to nil, and will always be nil and that's stupid so Xcode is saying not-accepted.  
    // Technically speaking you have a way around it🤓, you can help the compiler and enforce your value as a constant. See Option3
}

D'autres ont mentionné que Soit vous créez des initialiseurs, soit vous en faites des types facultatifs, en utilisant! ou ? qui est correct. Cependant, si vous avez un membre / propriété optionnel, celui-ci doit être mutable, c'est-à-dire var. Si vous en faites un, letil ne pourra jamais sortir de son nilétat. C'est mauvais!

La manière correcte de l'écrire est donc:

Option 1

class Actor {
    var agent : String? // It's defaulted to `nil`, but also has a chance so it later can be set to something different || GOOD!
}

Ou vous pouvez l'écrire comme:

Option 2

class Actor {
let agent : String? // It's value isn't set to nil, but has an initializer || GOOD!

init (agent: String?){
    self.agent = agent // it has a chance so its value can be set!
    }
}

ou par défaut à n'importe quelle valeur (y compris nilce qui est un peu stupide)

Option3

class Actor {
let agent : String? = nil // very useless, but doable.
let company: String? = "Universal" 
}

Si vous êtes curieux de savoir pourquoi let(contrairement à var) n'est pas initialisé, nillisez ici et ici

Mon chéri
la source
2
Merci d'avoir ajouté ceci car c'était une partie critique de l'image.
Jim
Bien expliqué !!
Mahendra
1
Mettre à zéro n'est pas stupide, mais inhérent au nombre de modèles qui fonctionnent.
tirage ..
@drew .. définir quelque chose d'immuable nilest très faux. Définir un varto nilest une chose différente.
Honey
hey Honey, qui parlait à des objets immuables?
tiré
11

Dans mon cas, j'ai déclaré un Boolcomme ceci:

var isActivityOpen: Bool 

c'est-à-dire que je l'ai déclaré sans le déballer, c'est ainsi que j'ai résolu l' erreur ( pas d'initialisation ):

var isActivityOpen: Bool!
Anurag Sharma
la source
1

Pas de réponse spécifique à votre question, mais j'avais eu cette erreur lorsque je n'avais pas défini une valeur initiale pour une énumération tout en la déclarant comme une propriété. J'ai attribué une valeur initiale à l'énumération pour résoudre cette erreur. Publier ici car cela pourrait aider quelqu'un.

Sonu VR
la source
0

fournissez simplement le bloc d' initialisation pour la classe HomeCell

ça marche dans mon cas

anoopbryan2
la source