【问题标题】:Error with Swift and Core Data: fatal error: use of unimplemented initializer 'init(entity:insertIntoManagedObjectContext:)'Swift 和 Core Data 出错:致命错误:使用未实现的初始化程序 'init(entity:insertIntoManagedObjectContext:)'
【发布时间】:2014-10-05 11:49:52
【问题描述】:

我有以下继承自 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)
    }

}

我发现通过将初始化器设置为方便并调用 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;

}

上面的代码有效,但我不知道为什么。有人知道发生了什么吗?是bug还是我的错?

【问题讨论】:

  • 你发现了吗?我觉得答案没有给出适当的解释。

标签: cocoa core-data swift initialization


【解决方案1】:

这是documented 的行为。

默认情况下,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 初始化器,那么它会自动继承其所有父类指定的初始化器,如“自动初始化器继承”部分所述

【讨论】:

  • 但是他的第一个代码是如何编译的呢?它不包括所有指定的初始化器,对吧?
【解决方案2】:

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

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

答案有点像回答,但不是直接回答。

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

如果你有NSManagedObject 基类,你也必须在这些基类中实现这个方法。

Credits to JSQCoreDataKit for the idea.

【讨论】:

  • 非常感谢,经过 3 小时的调查,您真的节省了我的时间,我刚刚覆盖了基类和子类的初始化程序,它工作正常
猜你喜欢
  • 2019-04-23
  • 1970-01-01
  • 1970-01-01
  • 2014-07-25
  • 2017-03-22
  • 1970-01-01
  • 1970-01-01
  • 2018-09-10
相关资源
最近更新 更多