使用Swift协议与泛型 [英] Using Swift protocols with generics

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

问题描述

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

  import CoreData 

@ objc协议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?()

会导致错误:


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


$ <$ p
$ b



编辑



删除 @optional 从声明和更改函数一点允许代码编译,但现在我得到一个运行时错误说,


'Swift动态转换失败'




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

class AbstractModel:NSManagedObject,CoreDataModel {

class func entityName() - > String {
returnAbstractModel
}

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


解决方案

我不能解释为什么你的代码导致运行时异常。但是如果你改变
的函数原型

  class func create< T:CoreDataModel>(aClass:类型,上下文:NSManagedObjectContext) - > T 

 code> class func create< T:NSManagedObject其中T:CoreDataModel>(aClass:T.Type,context:NSManagedObjectContext) - >假设您的托管对象子类符合协议,例如

$

  extension事件:CoreDataModel {
class func entityName() - > String {
returnEvent
}
}

这将工作并创建一个新对象:

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






或者,您可以使用从
Swift:return Array of type self
定义 NSManagedObjectContext 类的扩展:

 扩展NSManagedObjectContext {
func create< T:NSManagedObject其中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)


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

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

However, this line:

var name = T.entityName?()

causes the error:

Expected member name or constructor call after type name

Any idea what I'm doing wrong?

Edit

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

to

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)


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

Then a new object would be created as

let newManagedObject = context.create(Event.self)

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

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