我有一个CoreDataStore
类,该类具有两个通用占位符,可用于模型中的每种实体类型。这个想法是,它从商店中获取NSManagedObject
子类(基于一种通用类型),将其转换为适当的对象(基于另一种通用类型)并返回该对象。
此行为的目的是这样的,因此,我将核心数据方面保持封装状态,并避免在整个应用程序中传递NSManagedObject
实例。
示例潜在用法
这纯粹是如何使用法看起来进一步证明我要达到的目的。
let personStore = CoreDataStore<ManagedPerson, Person>()
let personData = personStore.fetchSomeObject() // personData is a value type Person
我有以下代码,分成多个文件,但为简单起见,此处以修改后的方式显示。
import Foundation
import CoreData
// MARK: - Core Data protocol and managed object
protocol ManagedObjectProtocol { }
class ManagedPerson: NSManagedObject, ManagedObjectProtocol {
var title: String?
}
class ManagedDepartment: NSManagedObject, ManagedObjectProtocol {
var name: String?
}
// MARK: - Simple struct representations
protocol DataProtocol {
typealias ManagedObjectType: ManagedObjectProtocol
init(managedObject: ManagedObjectType)
}
struct Person {
var title: String?
}
struct Department {
var name: String?
}
extension Person: DataProtocol {
typealias ManagedObjectType = ManagedPerson
init(managedObject: ManagedPerson) {
self.title = managedObject.title
}
}
extension Department: DataProtocol {
typealias ManagedObjectType = ManagedDepartment
init(managedObject: ManagedDepartment) {
self.name = managedObject.name
}
}
class CoreDataStore<ManagedObject: ManagedObjectProtocol, DataObject: DataProtocol> {
func fetchSomeObject() -> DataObject {
var managedObject: ManagedObject // fetch an NSManagedObject
// Error here
return DataObject(managedObject: managedObject)
}
}
我收到的错误是当我尝试初始化
fetchSomeObject
中的结构时:无法使用类型为((managedObject:ManagedObject)'的参数列表来调用类型为'DataObject'的初始化程序
显然,编译器无法弄清楚
DataObject
(仅限于符合DataProtocol
的类型)可以用ManagedObject
(仅限于符合ManagedObjectProtocol
的类型)初始化,尽管它已在DataProtocol
中声明。有什么方法可以实现此功能?另外,这是一种合理的方法还是我完全摆脱了这个障碍?
更新资料
经过一番挖掘后,看来Swift generics are invariant导致了我所遇到的问题。
最佳答案
再次考虑您的CoreDataStore
,例如CoreDataStore<ManagedPerson, Department>
没有任何意义。为什么不?因为Department
是没有问题的DataProtocol
,但是其对应的typealias ManagedObjectType
不是ManagedPerson
。
您的代码无法编译的原因是相同的。在return DataObject(managedObject: managedObject)
中,您不能从任意DataObject
初始化ManagedObject
,仅可接受DataObject.ManagedObjectType
。
因此,您需要的是类型约束,添加此where子句,您的代码应该可以工作:
class CoreDataStore<ManagedObject: ManagedObjectProtocol, DataObject: DataProtocol
where DataObject.ManagedObjectType == ManagedObject>
关于ios - 以“通用”方式将NSManagedObjects转换为结构(Swift),我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/33218100/