使用带有泛型的 Swift 协议 [英] Using Swift protocols with generics

查看:25
本文介绍了使用带有泛型的 Swift 协议的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个简单的例子,看起来应该可以工作:

I have a simple example that seems like it should work:

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.

So we have a class called AbstractModel which conforms to the protocol CoreDataModel, and CoreDataModel defines an optional class method called entityName.

然而,这一行:

var name = T.entityName?()

导致错误:

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

Expected member name or constructor call after type name

知道我做错了什么吗?

从声明中删除单词 @optional 并稍微改变函数允许代码编译,但现在我收到一个运行时错误说

Removing the word @optional from the declaration and changing the function a bit allows the code to compile, but now I get a runtime error saying that the

'Swift 动态转换失败'

'Swift dynamic cast failed'

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

推荐答案

我无法解释为什么您的代码会导致运行时异常.但如果你改变它就会起作用函数原型

I cannot explain why your code causes a runtime exception. But it works if you change the function prototype

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

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

Assuming that your managed object subclass conforms to the protocol, for example

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

然后这会起作用并创建一个新对象:

then this works and creates a new object:

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

<小时>

或者,您可以使用答案中的方法Swift:返回 self 类型的数组"和定义对 NSManagedObjectContext 类的扩展:


Alternatively, you could use the approach from the answer to "Swift: return Array of type self" and define an extension to the NSManagedObjectContext class:

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)

这篇关于使用带有泛型的 Swift 协议的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆