2014-10-05 14 views
8

Ho il seguente classe che eredita da NSManagedObject:errore con Swift e Core Data: errore fatale: l'uso di initializer implementato 'init (entità: insertIntoManagedObjectContext :)'

import Foundation 
import CoreData 


class Note: NSManagedObject { 



    @NSManaged var text: String 
    @NSManaged var name: String 


    init(name: String, text:String, context: NSManagedObjectContext){ 

     let entity = NSEntityDescription.entityForName("Note", inManagedObjectContext: context); 
     super.init(entity: entity!, insertIntoManagedObjectContext: context) 

     self.text = text 
     self.name = name; 

    } 
} 

Quando creo istanze di esso, tutto funziona bene, ma quando faccio una ricerca di queste entità, ottengo un errore molto strano:

fatal error: use of unimplemented initializer 'init(entity:insertIntoManagedObjectContext:)' 

Questo è il codice che causa l'errore:

func coreDatePlayground(){ 

    var note = Note(name: "A new note", text: "blah", context: self.managedObjectContext!) 

    println("\(note.name) \(note.text)") 

    var noote2 = Note(name: "Another note", text: "blah blah", context: self.managedObjectContext!) 


    managedObjectContext?.save(nil) 

    var fetch = NSFetchRequest(entityName: "Note") 
    // This line causes the crash. 
    var results = self.managedObjectContext?.executeFetchRequest(fetch, error: nil) 
    if let objects = results{ 
     println(objects.count) 
    } 

} 

Ho scoperto che cambiare l'inizializzatore rendendolo più comodo e chiamare su sé invece che su super elimina il problema, ma non ho idea del perché.

convenience init(name: String, text:String, context: NSManagedObjectContext){ 

    let entity = NSEntityDescription.entityForName("Note", inManagedObjectContext: context); 
    self.init(entity: entity!, insertIntoManagedObjectContext: context) 

    self.text = text 
    self.name = name; 

} 

Il codice sopra funziona, ma non ho idea del perché. Qualcuno sa cosa sta succedendo? È un bug o è colpa mia?

+0

Hai capito? Non ho la sensazione che la risposta dia una spiegazione adeguata. – kgaidis

risposta

11

Questo è il comportamento documented.

Swift subclasses do not inherit their superclass initializers by default

Ad esempio, codice seguente non ha nemmeno compilare, perché Child non eredita init(id:String) automaticamente. Questo meccanismo si assicura che name nella classe Child inizializzata correttamente.

class Parent { 
    var id:String 
    init(id:String) { 
     self.id = id 
    } 
} 

class Child:Parent { 
    var name:String 
    init(id:String, name:String) { 
     self.name = name 
     super.init(id: id) 
    } 
} 

var child1 = Child(id:"child1") 

Se si definisce solo convenience inizializzatori in sottoclasse, allora eredita automaticamente tutti i suoi superclasse designato inizializzatori come documentato nella sezione "Automatico Initializer Inheritance"

+3

Ma come si compila il suo primo codice allora? Non include tutti gli inizializzatori designati giusto? – Fr4nc3sc0NL

4

È necessario implementare quanto segue nel NSManagedObject sottoclasse (questo è la versione Swift 3.0):

@objc 
private override init(entity: NSEntityDescription, insertInto context: NSManagedObjectContext?) { 
    super.init(entity: entity, insertInto: context) 
} 

La risposta è una specie di risposta, ma non direttamente.

Il ragionamento per questo è che la Swift non eredita i loro supercalls inizializzatori designati per default E sembra come CoreData da usi questo inizializzatore quando si fa recupera (inserire un punto di interruzione nel metodo per vedere). Quindi qui "richiamiamo" l'inizializzatore designato per l'uso di CoreData.

Se si dispone di classi base NSManagedObject, è necessario implementare questo metodo anche in tali.

Credits to JSQCoreDataKit for the idea.

+0

Brillante! .... – GK100

Problemi correlati