2014-10-05 18 views
8

Mam następujące klasy, która dziedziczy NSManagedObject:Błąd Swift i danych Core: błąd krytyczny: wykorzystanie ZAIMPLEMENTOWANE inicjatora 'init (jednostka: 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; 

    } 
} 

Kiedy tworzyć instancje niego wszystko działa poprawnie, ale kiedy robię poszukiwania tych podmiotów, mam bardzo dziwny błąd:

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

jest to kod, który powoduje błąd:

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) 
    } 

} 

Dowiedziałem się, że zmiana inicjalizatora, czyniąc go wygodnym i wzywaniem siebie zamiast na super pozbywa się problemu, ale nie mam pojęcia dlaczego.

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; 

} 

Powyższy kod działa, ale nie mam pojęcia, dlaczego. Ktoś wie, co się dzieje? Czy to błąd, czy moja wina?

+0

Czy to wymyśliłeś? Nie wydaje mi się, żeby ta odpowiedź była właściwym wyjaśnieniem. – kgaidis

Odpowiedz

11

To jest zachowanie documented.

Swift subclasses do not inherit their superclass initializers by default

Na przykład, poniższy kod nie nawet skompilować, bo Child nie dziedziczy init(id:String) automatycznie. Ten mechanizm zapewnia prawidłowe zainicjowanie klasy name w klasie .

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") 

Jeśli definiować tylko convenience inicjatorów w podklasie, to automatycznie dziedziczy wszystkie nadklasy wyznaczony inicjalizatorów jak udokumentowano w sekcji „Automatyczne Initializer dziedziczenie”

+3

Ale jak działa jego pierwszy kod? Nie obejmuje wszystkich wyznaczonych praw inicjujących? – Fr4nc3sc0NL

4

Należy wdrożyć następujących w NSManagedObject podklasy (tym to wersja Swift 3.0):

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

Odpowiedź jest odpowiedzią na to, ale nie bezpośrednio.

Rozumowanie jest to, że Swift nie dziedziczą supercalls wyznaczone inicjatorów domyślnie I Wydaje się CoreData przez używa tego initializer robiąc pobieraniom (wstawić przerwania w metodzie aby zobaczyć). Tak więc tutaj "wywołujemy" wskazany inicjator CoreData do użycia.

Jeśli masz klasy bazowe NSManagedObject, musisz również zaimplementować tę metodę w tych.

Credits to JSQCoreDataKit for the idea.

+0

Genialny! .... – GK100