使用带有泛型的 Swift 协议 [英] Using Swift protocols with generics
问题描述
我有一个简单的例子,看起来应该可以工作:
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屋!