Согласовать удаленный CKRecord с CoreData NSManagedObject - PullRequest
0 голосов
/ 04 ноября 2019

Я создал CKQuerySubscription с для мониторинга удаленной вставки, изменения и удаления CKRecord с. Для вставленных и измененных записей это работает хорошо, потому что я могу запросить CloudKit для затронутого CKRecord, получить связанный NSManagedObject, а затем обработать вставку и изменение оттуда.

Для удаленных CKRecord s, это проблема, потому что к тому времени, когда уведомление было запущено, CKRecord уже был удален из CloudKit. Это означает, что запрос на выборку для получения удаленного CKRecord завершился неудачей, поэтому у меня нет возможности узнать, какой NSManagedObject был связан с удаленным CKRecord.

. Не знаю,все идет не так, и если есть простой способ справиться со всем этим!

1 Ответ

0 голосов
/ 04 ноября 2019

Это работает, но кажется немного неуклюжим. Должен быть более простой способ! Но если нет, если этот код полезен кому-либо еще, не стесняйтесь комментировать, если вы хотите, чтобы код, использованный в любом из вспомогательных методов, не показывался (например, в методе +[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];
    });
}];
...