我有一个 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
中的结构时:
Cannot invoke initializer for type 'DataObject' with an argument list of type '(managedObject: ManagedObject)'
显然,编译器无法确定 DataObject
(仅限于符合 DataProtocol
的类型)可以使用 ManagedObject
进行初始化>(仅限于符合 ManagedObjectProtocol
的类型)尽管它在 DataProtocol
中被声明为此类。
有什么办法可以实现这个功能吗?此外,这是一种合理的方法还是我完全不接受这种方法?
更新
经过一番挖掘,似乎 Swift generics are invariant我认为这是导致我遇到的问题。
最佳答案
想想你的 CoreDataStore
再次,例如,CoreDataStore<ManagedPerson, Department>
没有任何意义。为什么不?因为Department
是 DataProtocol
没问题,但它对应的类型别名 ManagedObjectType
不是 ManagedPerson
.
您的代码无法编译的原因是一样的。这里return DataObject(managedObject: managedObject)
你不能初始化 DataObject
来自 armbitary ManagedObject
, 只有一个 DataObject.ManagedObjectType
是可以接受的。
所以你需要的是一个类型约束,添加这个 where 子句,你的代码应该可以工作:
class CoreDataStore<ManagedObject: ManagedObjectProtocol, DataObject: DataProtocol
where DataObject.ManagedObjectType == ManagedObject>
关于ios - 以 "generic"方式将 NSManagedObject 转换为结构体 (Swift),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33218100/