web-dev-qa-db-fra.com

Comment créer un initialiseur désigné pour la sous-classe NSManagedObject dans Swift?

class Alternative: NSManagedObject {

    @NSManaged var text: String
    @NSManaged var isCorrect: Bool
    @NSManaged var image: NSData
} 

convenience init(text: String, isCorrect: Bool, entity: NSEntityDescription, insertIntoManagedObjectContext context: NSManagedObjectContext!) {
        let alternative = Alternative(entity: entity, insertIntoManagedObjectContext: context) as Alternative
        alternative.text = text
        alternative.isCorrect = isCorrect
        return alternative
}

Je veux créer une méthode qui me permet d'initialiser de nouveaux objets avec cet appel:

let newAlternative = Alternative("third platform", True, entityDescription, managedObjectContext)

Mais je reçois l'erreur:

Convenience initializer for Alternative must delegate with self.init

Que dois-je changer dans mon initalizer pour que mon exemple d'utilisation fonctionne?

30
bogen

Un initialiseur de commodité doit appeler l'initialiseur désigné sur self:

convenience init(text: String, isCorrect: Bool, entity: NSEntityDescription, insertIntoManagedObjectContext context: NSManagedObjectContext!) {
    self.init(entity: entity, insertIntoManagedObjectContext: context)
    self.text = text
    self.isCorrect = isCorrect
}

qui serait appelé

let newAlternative = Alternative(text: "third platform", isCorrect: true,
     entity: entityDescription, insertIntoManagedObjectContext: managedObjectContext)

De plus, vous pouvez également déplacer la création de la description de l'entité dans l'initialiseur de commodité au lieu de la passer comme argument (comme motivé par la réponse de Mundi):

convenience init(text: String, isCorrect: Bool, insertIntoManagedObjectContext context: NSManagedObjectContext!) {
    let entity = NSEntityDescription.entityForName("Alternative", inManagedObjectContext: context)!
    self.init(entity: entity, insertIntoManagedObjectContext: context)
    self.text = text
    self.isCorrect = isCorrect
}
36
Martin R

J'ai simplement fait cela avec une fonction de classe:

class func newInstance(text: String, notes:String, 
                    context: NSManagedObjectContext) -> Item {
    var item = NSEntityDescription.insertNewObjectForEntityForName("Item", 
               inManagedObjectContext: context) as Item
    item.notes = notes
    item.text = text
    return item
}

que vous pouvez appeler comme ça (presque aussi joli):

let item = Item.newInstance(text, notes:notes, context:context)
10
Mundi

Swift 3.1 solution:

convenience init(text: String, isCorrect: Bool, image: NSData, moc: NSManagedObjectContext) {
        let entity = NSEntityDescription.entity(forEntityName: "Alternative", in: moc)
        self.init(entity: entity!, insertInto: moc)
        // vars
        self.text = text
        self.isCorrect = isCorrect
        self.image = image
}
3
Alessandro Ornano

Vous devez appeler un initialiseur désigné à partir de votre initialiseur de commodité. En outre, vous ne renvoyez rien à partir d'un initialiseur.

Pour respecter les règles, qui sont décrites dans la documentation Apple Swift, vous avez d'abord besoin d'un initialiseur désigné pour votre sous-classe, qui appelle l'init () de sa superclasse, alors vous pouvez proposer un initialiseur pratique qui est uniquement autorisé à appeler un initialiseur désigné à partir de sa déclaration de classe.

Cela fonctionnerait: (Mise à jour: Compte tenu du fait que les propriétés de données de base marquées avec @NSManaged sont initialisées automatiquement par le runtime. Merci @Martin R)

init(text: String, isCorrect: Bool, image: NSData, entity: NSEntityDescription,   insertIntoManagedObjectContext context: NSManagedObjectContext!) {
    super.init(entity: entity, insertIntoManagedObjectContext: context)
}

convenience init(text: String, isCorrect: Bool, entity: NSEntityDescription, insertIntoManagedObjectContext context: NSManagedObjectContext!) {
    self.init(text: text, isCorrect: isCorrect, entity: entity, insertIntoManagedObjectContext: context)
}
2
marcusficner