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

时间:2022-09-07 07:54:20

I have the following class that inherits from NSManagedObject:

我有以下从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;

    }
}

When I create instances of it, everything works fine, but when I make a search for these entities, I get a very odd error:

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

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

This is the code that causes the error:

这是导致错误的代码:

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

}

I found out that changing the initialiser by making it a convenience one and calling on self instead of on super gets rid of the issue, but I have no idea why.

我发现改变初始化的方法是让它变得方便,并且调用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;

}

The code above works, but I have no idea why. Anybody knows what's going on? Is it a bug or is my fault?

上面的代码有效,但我不知道为什么。谁知道发生了什么事?这是一个错误还是我的错?

2 个解决方案

#1


11  

This is documented behavior.

这是记录在案的行为。

Swift subclasses do not inherit their superclass initializers by default

默认情况下,Swift子类不继承其超类初始值设定项

For example, following code does not even compile, because Child does not inherit init(id:String) automatically. This mechanism make sure name in Child class properly initialized.

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

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

If you define only convenience initializers in subclass, then it automatically inherits all of its superclass designated initializers as documented in "Automatic Initializer Inheritance" section

如果在子类中仅定义了便利初始值设定项,那么它会自动继承其所有超类指定的初始值设定项,如“自动初始化程序继承”部分中所述

#2


5  

You must implement the following in your NSManagedObject subclass (this is the Swift 3.0 version):

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

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

The answer is kind of answering it, but not really directly.

答案是回答它,但不是直接回答。

The reasoning for this is that Swift does not inherit their supercalls designated initializers by default AND it seems as CoreData by uses this initializer when doing fetches (insert a breakpoint in the method to see). So here we "bring up" the designated initializer for CoreData to use.

这样做的原因是Swift默认不继承它们的超级调用指定的初始化器,并且在执行读取时使用此初始化器似乎是CoreData(在方法中插入断点)。所以这里我们“调出”指定的CoreData初始化程序。

If you have NSManagedObject base classes, you must also implement this method in those.

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

Credits to JSQCoreDataKit for the idea.

致JSQCoreDataKit的想法。

#1


11  

This is documented behavior.

这是记录在案的行为。

Swift subclasses do not inherit their superclass initializers by default

默认情况下,Swift子类不继承其超类初始值设定项

For example, following code does not even compile, because Child does not inherit init(id:String) automatically. This mechanism make sure name in Child class properly initialized.

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

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

If you define only convenience initializers in subclass, then it automatically inherits all of its superclass designated initializers as documented in "Automatic Initializer Inheritance" section

如果在子类中仅定义了便利初始值设定项,那么它会自动继承其所有超类指定的初始值设定项,如“自动初始化程序继承”部分中所述

#2


5  

You must implement the following in your NSManagedObject subclass (this is the Swift 3.0 version):

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

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

The answer is kind of answering it, but not really directly.

答案是回答它,但不是直接回答。

The reasoning for this is that Swift does not inherit their supercalls designated initializers by default AND it seems as CoreData by uses this initializer when doing fetches (insert a breakpoint in the method to see). So here we "bring up" the designated initializer for CoreData to use.

这样做的原因是Swift默认不继承它们的超级调用指定的初始化器,并且在执行读取时使用此初始化器似乎是CoreData(在方法中插入断点)。所以这里我们“调出”指定的CoreData初始化程序。

If you have NSManagedObject base classes, you must also implement this method in those.

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

Credits to JSQCoreDataKit for the idea.

致JSQCoreDataKit的想法。