将已删除的 CKRecord 与 CoreData NSManagedObject 协调一致
Posted
技术标签:
【中文标题】将已删除的 CKRecord 与 CoreData NSManagedObject 协调一致【英文标题】:Reconcile deleted CKRecord to CoreData NSManagedObject 【发布时间】:2019-11-04 09:37:25 【问题描述】:我创建了CKQuerySubscription
s 来监控CKRecord
s 的远程插入、修改和删除。对于插入和修改的记录,这很有效,因为我可以查询CloudKit
以获取受影响的CKRecord
,获取关联的NSManagedObject
,然后从那里处理插入和修改。
对于已删除的CKRecord
s,这是一个问题,因为在触发通知时,CKRecord
已从CloudKit
中删除。这意味着获取现已删除的CKRecord
的获取请求失败,因此我无法知道哪个NSManagedObject
与已删除的CKRecord
相关联。
我不知道我是否会以错误的方式处理这一切,是否有更简单的方法来处理所有这些!
【问题讨论】:
【参考方案1】:这行得通,但感觉有点笨拙。一定有更简单的方法!但如果不是,如果此代码对其他人有用,如果您希望在任何未显示的辅助方法中使用的代码(例如在 +[CoreDataFunctions fetchRecordsForEntityType: withCloudIDs: completion:]
方法中),请随时发表评论;
//Array to hold all cloudIDs of existing NSManagedObject instances
NSMutableArray *cloudIDs = [NSMutableArray array];
//Populate cloudIDs array with the IDs of the existing NSManagedObject instances
for (NSManagedObject *item in self.items)
NSUUID *cloudID = [item valueForKey:@"cloudID"];
[cloudIDs addObject:cloudID];
//Array to hold remaining NSManagedObject instances (i.e. the ones which were not deleted)
NSMutableArray *remainingItems = [NSMutableArray array];
//Fetch all remaining CKRecords (i.e. the ones which were not deleted
[CoreDataFunctions fetchRecordsForEntityType:[self managedObjectMonitoringClass] withCloudIDs:cloudIDs completion:^(NSArray<CKRecord *> *results)
//For each local NSManagedObject instance
for (NSManagedObject *item in self.items)
//The cloudID for the local NSManagedObject instance
NSString *localCloudID = [[item valueForKey:@"cloudID"] UUIDString];
//For each CKRecord in CloudKit
for (CKRecord *record in results)
//The cloudID for the remote CKRecord object
NSString *remoteCloudID = [record valueForKey:@"CD_cloudID"];
//If the local and remote cloudIDs match, the local NSManagedObject entity represents a CKRecord which still exists in CloudKit
//Add the NSManagedObject entity to the remainingItems array
if ([remoteCloudID isEqualToString:localCloudID])
[remainingItems addObject:item];
break;
//Array to hold NSIndexPath objects to be removed from the collectionView
NSMutableArray *indexPaths = [NSMutableArray array];
//For each NSManagedObject stored locally
for (NSManagedObject *item in self.items)
//If the remainingItems array does not contain this NSManagedObject, it has been deleted from CloudKit
//Create and indexPath for this item and add it to the array
if (![remainingItems containsObject:item])
NSInteger index = [self.items indexOfObject:item];
[indexPaths addObject:[NSIndexPath indexPathForItem:index inSection:0]];
dispatch_async(dispatch_get_main_queue(), ^
[[self TBcollectionView] performBatchUpdates:^
//Set the local items array to whatever is remaining in CloudKit
self.items = remainingItems;
//Delete the indexPaths for the items which were deleted
[[self TBcollectionView] deleteItemsAtIndexPaths:indexPaths];
completion:nil];
);
];
【讨论】:
【参考方案2】:我使用带有远程通知和 CKFetchRecordZoneChangesOperation 的订阅。
如果调用“application(didReceiveRemoteNotification:)”方法,如果构建并触发“CKFetchRecordZoneChangesOperation”。
有几个完成处理程序。一种用于更新记录(添加/修改),另一种用于已删除记录。
此处理程序称为“recordWithIDWasDeletedBlock”,并为已删除的每条记录调用,并提供已删除记录的记录ID。有了这些信息,您应该能够处理您需要的内容。
【讨论】:
以上是关于将已删除的 CKRecord 与 CoreData NSManagedObject 协调一致的主要内容,如果未能解决你的问题,请参考以下文章
在表视图或集合视图中删除与 IndexPath 关联的 CKRecord 的稳健方法是啥?