gpt4 book ai didi

swift - 使用通用函数从云记录(或其他外部源)填充对象

转载 作者:搜寻专家 更新时间:2023-10-30 21:59:44 25 4
gpt4 key购买 nike

我正在为我的 Swift 应用程序构建通用 API。我使用 CoreData 进行本地存储,使用 CloudKit 进行云同步。

为了能够在通用函数中使用我的数据对象,我将它们组织如下(简要总结):

  • CoreData 数据库中的对象是 NSManagedObject 实例,它们符合名为 ManagedObjectProtocol 的协议(protocol),可以转换为 DataObject 实例
  • NSManagedObject 需要进行云同步,符合名为 CloudObject 的协议(protocol),该协议(protocol)允许从记录中填充对象,反之亦然
  • 我在应用程序的图形层中使用的对象是符合 DataObject 协议(protocol)的 NSObject 类,该协议(protocol)允许转换为 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)
}
}
}

但是,这给了我几个错误:

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

CloudObject 协议(protocol)如下所示:

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
}

不知何故,我需要找到一种方法,使我能够根据收到的 recordType 获取符合 CloudObject 的特定类。我最好怎么做?

如有任何帮助,我们将不胜感激!

最佳答案

由于 CoreData 和 CloudKit 的数据格式不相关,您需要一种方法来有效地从 CloudKit 记录中识别 CoreData 对象,反之亦然。

我的建议是对 CloudKit 记录类型和 CoreData 实体使用相同的名称,并使用格式为 <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!)
}
}

CKRecord 的扩展从 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)
}
}

当您收到云记录时,提取实体和唯一标识符。然后尝试获取相应的 CoreData 对象。如果对象存在更新它,如果不存在则创建一个新对象。另一方面,从具有唯一记录名称的 CoreData 对象创建新记录。你的CloudObject协议(protocol)广泛适用于此模式,不需要关联类型(通过删除它消除错误的方式)但添加要求 recordName

var recordName : String { get set }

和获得 recordID 的扩展来自记录名

extension CloudObject where Self : NSManagedObject {

var recordID : CKRecordID {
return CKRecordID(recordName: self.recordName, zoneID: CloudManager.shared.zoneID)
}
}

关于swift - 使用通用函数从云记录(或其他外部源)填充对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51322828/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com