Swift和Core Data错误:致命错误:使用未实现的初始化程序'init(entity:insertIntoManagedObjectContext :)'

13

我有一个继承自NSManagedObject的类:

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;

    }
}

当我创建这些实例时,一切都正常,但当我搜索这些实体时,我会收到一个非常奇怪的错误:

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

这是导致错误的代码:

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

}

我发现通过将初始化程序更改为convenience类型,并在self上调用而不是在super上调用可以解决这个问题,但我不知道为什么。

 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;

}

上面的代码可以运行,但我不知道为什么。有人知道发生了什么吗?是一个错误还是我的问题?


你解决了吗?我觉得答案没有给出适当的解释。 - kgaidis
2个回答

16

这是已记录下来的行为。

默认情况下,Swift 子类不会继承其父类初始化方法。

例如,以下代码甚至不能编译,因为Child不会自动继承init(id:String)。这个机制确保了Child类中的name被正确初始化。

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

如果您在子类中仅定义了convenience初始化程序,则它会自动继承其所有超类指定的初始化程序,如“自动初始化程序继承”部分所述


3
他的第一份代码是如何编译的呢?它并没有包含所有指定的初始化器,对吗? - Fr4nc3sc0NL

13

在你的NSManagedObject子类中必须实现以下内容(这是Swift 3.0版本):

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

回答有点在回答,但并不是非常直接。

这是因为Swift默认不继承它们的supercalls指定初始化程序 AND CoreData似乎在执行获取(fetch)时使用此初始化程序(在方法中插入断点以查看)。所以在这里我们“提出”了CoreData要使用的指定初始化程序。

如果您有NSManagedObject基类,您还必须在这些类中实现此方法。

感谢JSQCoreDataKit提供的想法.


2
非常感谢您,您真的节省了我的时间。经过3个小时的调查,我刚刚在基类和子类上覆盖了初始化程序,现在它可以正常工作了。 - Yahya Alshaar

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接