Jor*_*416 7 generics protocols core-data swift swift-protocols
我正在为我的Swift应用程序构建通用API.我CoreData
用于本地存储和CloudKit
云同步.
为了能够在泛型函数中使用我的数据对象,我将它们组织如下(简要摘要):
CoreData
数据库的对象是NSManagedObject
符合所调用协议的实例ManagedObjectProtocol
,可以转换为DataObject
实例NSManagedObject
需要进行云同步的s符合一个CloudObject
允许从记录中填充对象的协议,反之亦然DataObject
允许转换为NSManagedObject
实例的协议特定类的对象.我希望这段代码看起来像这样:
for record in records {
let context = self.persistentContainer.newBackgroundContext()
//classForEntityName is a function in a custom extension that returns an NSManagedObject for the entityName provided.
//I assume here that recordType == entityName
if let managed = self.persistentContainer.classForEntityName(record!.recordType) {
if let cloud = managed as? CloudObject {
cloud.populateManagedObject(from: record!, in: context)
}
}
}
Run Code Online (Sandbox Code Playgroud)
但是,这给了我几个错误:
Protocol 'CloudObject' can only be used as a generic constraint because it has Self or associated type requirements
Member 'populateManagedObject' cannot be used on value of protocol type 'CloudObject'; use a generic constraint instead
Run Code Online (Sandbox Code Playgroud)
CloudObject协议如下所示:
protocol CloudObject {
associatedtype CloudManagedObject: NSManagedObject, ManagedObjectProtocol
var recordID: CKRecordID? { get }
var recordType: String { get }
func populateManagedObject(from record: CKRecord, in context: NSManagedObjectContext) -> Promise<CloudManagedObject>
func populateCKRecord() -> CKRecord
}
Run Code Online (Sandbox Code Playgroud)
不知何故,我需要找到一种方法,允许我CloudObject
根据recordType
我收到的特定类符合.我最好怎么做呢?
任何帮助将非常感激!
由于 CoreData 和 CloudKit 的数据格式不相关,因此您需要一种方法来有效地从 CloudKit 记录中识别 CoreData 对象,反之亦然。
我的建议是对 CloudKit 记录类型和 CoreData 实体使用相同的名称,并使用 format 的自定义记录名称(字符串)<Entity>.<identifer>
。Entity
是记录类型/类名,标识符是具有唯一值的CoreData 属性。例如,如果有两个名为的实体Person
,且Event
记录名称为"Person.JohnDoe"
或"Event.E71F87E3-E381-409E-9732-7E670D2DC11C"
。如果存在 CoreData 关系,请添加更多点分隔组件来识别这些关系
为了方便起见,您可以使用辅助枚举Entity
从记录创建适当的实体
enum Entity : String {
case person = "Person"
case event = "Event"
init?(record : CKRecord) {
let components = record.recordID.recordName.components(separatedBy: ".")
self.init(rawValue: components.first!)
}
}
Run Code Online (Sandbox Code Playgroud)
CKRecord
以及从 a 为特定记录类型创建记录的扩展Entity
(在我的示例中CloudManager
是一个用于管理 CloudKit 内容(例如区域)的单例)
extension CKRecord {
convenience init(entity : Entity) {
self.init(recordType: entity.rawValue, zoneID: CloudManager.shared.zoneID)
}
convenience init(entity : Entity, recordID : CKRecordID) {
self.init(recordType: entity.rawValue, recordID: recordID)
}
}
Run Code Online (Sandbox Code Playgroud)
当您收到云记录时,提取实体和唯一标识符。然后尝试获取对应的CoreData对象。如果对象存在则更新它,如果不存在则创建一个新对象。另一方面,从具有唯一记录名称的 CoreData 对象创建新记录。您的CloudObject
协议广泛适合此模式,不需要关联的类型(顺便说一下,删除它可以消除错误),但添加一个要求recordName
var recordName : String { get set }
Run Code Online (Sandbox Code Playgroud)
recordID
以及从记录名称中获取 的扩展
extension CloudObject where Self : NSManagedObject {
var recordID : CKRecordID {
return CKRecordID(recordName: self.recordName, zoneID: CloudManager.shared.zoneID)
}
}
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
151 次 |
最近记录: |