一尘不染

将Swift协议与泛型一起使用

swift

我有一个简单的示例,它似乎应该工作:

import CoreData

@objc protocol CoreDataModel {
    @optional class func entityName() -> String
}

class AbstractModel: NSManagedObject, CoreDataModel {
    class func create<T : CoreDataModel>(context:NSManagedObjectContext) -> T {
        var name = T.entityName?()
        var object = NSEntityDescription.insertNewObjectForEntityForName(name, inManagedObjectContext: context) as T
        return object
    }
}

因此,我们有一个名为的类AbstractModel,它符合协议CoreDataModel,并CoreDataModel定义了一个可选的类方法entityName

但是,这一行:

var name = T.entityName?()

导致错误:

类型名称后的预期成员名称或构造函数调用

知道我在做什么错吗?

编辑

@optional从声明中删除单词并稍微更改函数可以使代码得以编译,但是现在我遇到了运行时错误,指出

“快速动态投放失败”

@objc protocol CoreDataModel {
     class func entityName() -> String
}

class AbstractModel: NSManagedObject, CoreDataModel {

    class func entityName() -> String {
        return "AbstractModel"
    }

    class func create<T : CoreDataModel>(aClass:T.Type, context:NSManagedObjectContext) -> T {
        var name = aClass.entityName()
        var object = NSEntityDescription.insertNewObjectForEntityForName(name, inManagedObjectContext: context) as T
        return object
    }
}

阅读 399

收藏
2020-07-07

共1个答案

一尘不染

我无法解释为什么您的代码会导致运行时异常。但是,如果您更改函数原型,它将起作用

class func create<T : CoreDataModel>(aClass:T.Type, context:NSManagedObjectContext) -> T

class func create<T : NSManagedObject where T: CoreDataModel>(aClass:T.Type, context:NSManagedObjectContext) -> T

假设您的托管对象子类符合协议,例如

extension Event : CoreDataModel {
    class func entityName() -> String {
        return "Event"
    }
}

然后工作并创建一个新对象:

let newManagedObject = AbstractModel.create(Event.self, context: context)

或者,您可以使用从答案到“Swift:返回类型为self的数组”的方法,并定义NSManagedObjectContext该类的扩展:

extension NSManagedObjectContext {
    func create<T : NSManagedObject where T : CoreDataModel >(entity: T.Type) -> T {
        var classname = entity.entityName()
        var object = NSEntityDescription.insertNewObjectForEntityForName(classname, inManagedObjectContext: self) as T
        return object
    }
}

然后将创建一个新对象

let newManagedObject = context.create(Event.self)
2020-07-07