Fetching Changed Data from Cloudkit Server

Hello Sir/Mam


I am trying to implement Cloud sync in my application and I have implemented cloudkit framework also.Now I am trying to fetch record changes with CKFetchRecordZoneChangesOperation.

But I am getting operation error :


[LogFacilityCK] Got a connection error for operation B2EC16FD78756E1A: Error Domain=NSCocoaErrorDomain Code=4097 "connection to service named com.apple.cloudd" UserInfo={NSDebugDescription=connection to service named com.apple.cloudd}

When I am sending nil PreviousServerchangetoken that time it works great but when I am attaching CKFetchRecordZoneChangesOptions that time it throws error.

Please Help Me

Below is my code:

- (void)_fetchRecordChangesWithCompletionHandler:
(void (^)(UIBackgroundFetchResult result, BOOL moreComing))completionHandler
{
    CKServerChangeToken *prevServerChangeToken = nil;
    if ([[NSUserDefaults standardUserDefaults]objectForKey:KPREVSERVERCHANGETOKEN] != nil) {
        prevServerChangeToken = [[NSUserDefaults standardUserDefaults]objectForKey:KPREVSERVERCHANGETOKEN];
    }
    [self _fetchRecordChangesWithPrevServerChangeToken:prevServerChangeToken
                                    completionHandler:completionHandler];
}
- (void)_fetchRecordChangesWithPrevServerChangeToken:(CKServerChangeToken *)prevServerChangeToken
                                  completionHandler:
    (void (^)(UIBackgroundFetchResult result, BOOL moreComing))completionHandler
{

    CKRecordZoneID *recordZoneID = [[CKRecordZoneID alloc] initWithZoneName:CloudKitZoneName ownerName:CKOwnerDefaultName];

    CKFetchRecordZoneChangesOperation *operation;
    if(prevServerChangeToken == nil)
    {
        operation = [[CKFetchRecordZoneChangesOperation alloc]initWithRecordZoneIDs:@[ recordZoneID ] optionsByRecordZoneID:nil];
    }
    else{
        CKFetchRecordZoneChangesOptions *option = [[CKFetchRecordZoneChangesOptions alloc]init];
        option.previousServerChangeToken = prevServerChangeToken;
        operation = [[CKFetchRecordZoneChangesOperation alloc]initWithRecordZoneIDs:@[ recordZoneID ] optionsByRecordZoneID:@{ recordZoneID :option }];

    }

    __block NSMutableArray *deletedRecordIDs = nil;
    __block NSMutableArray *changedRecords = nil;
    __block NSString *serevrChangeToken ;

    operation.recordWithIDWasDeletedBlock = ^(CKRecordID *recordID,NSString *recType){

        if (deletedRecordIDs == nil)
            deletedRecordIDs = [[NSMutableArray alloc] init];

        [deletedRecordIDs addObject:recordID];
    };

    operation.recordChangedBlock = ^(CKRecord *changedRecord)
    {
        if (changedRecords == nil)
            changedRecords = [[NSMutableArray alloc] init];

        [changedRecords addObject:changedRecord];
    };
    operation.recordZoneChangeTokensUpdatedBlock = ^(CKRecordZoneID *recZoneID, CKServerChangeToken *serverchngToken, NSData *clientChangeTokenData)
    {
        serevrChangeToken = [NSString stringWithFormat:@"%@",serverchngToken];
    };

    operation.recordZoneFetchCompletionBlock = ^(CKRecordZoneID *recZONEID, CKServerChangeToken *serverchngToken, NSData *clientChangeTokenData, BOOL moreComing, NSError *  recordZoneError)
    {

        BOOL hasChanges = NO;
        if (!recordZoneError)
        {
            if (deletedRecordIDs.count > 0)
                hasChanges = YES;
            else if (changedRecords.count > 0)
                hasChanges = YES;
        }
        if (recordZoneError)
        {
            NSInteger ckErrorCode = recordZoneError.code;
            if (ckErrorCode == CKErrorChangeTokenExpired)
            {
                /
                /
            }
     
            if (completionHandler) {
                dispatch_async(dispatch_get_main_queue(), ^{
                    completionHandler(UIBackgroundFetchResultFailed, NO);
                });
            }
            dispatch_resume(fetchQueue);
        }
        else if (!hasChanges && !moreComing)
        {
            [APPMANAGER saveServerChangeToken:serverchngToken];
     
            if (completionHandler) {
                dispatch_async(dispatch_get_main_queue(), ^{
                    completionHandler(UIBackgroundFetchResultNoData, NO);
                });
            }
            dispatch_resume(fetchQueue);
        }
        else/
        {
            NSBlockOperation *operation1 = [NSBlockOperation blockOperationWithBlock:^{
                /
                [APPMANAGER deletedRecordsFromiCloudServer:[deletedRecordIDs copy]];
            }];
     
            NSBlockOperation *operation2 = [NSBlockOperation blockOperationWithBlock:^{
                /
                [APPMANAGER checkIfRecordsExisted:[self mapFiles:changedRecords]];
            }];
     
            [operation2 addDependency:operation1];
     
            NSOperationQueue *queue = [[NSOperationQueue alloc] init];
            [queue addOperations:@[operation1, operation2] waitUntilFinished:NO];
     
            [queue setCompletion:^{
                /
                /
                serevrChangeToken = [NSString stringWithFormat:@"%@",serverchngToken];
                [APPMANAGER saveServerChangeToken:serevrChangeToken];
                /
                if (completionHandler)
                {
                    if (hasChanges)
                        completionHandler(UIBackgroundFetchResultNewData, moreComing);
                    else
                        completionHandler(UIBackgroundFetchResultNoData, moreComing);
                }
            }];
            if (moreComing) {
                [self _fetchRecordChangesWithCompletionHandler:completionHandler];
            }
            else {
                dispatch_resume(fetchQueue);
            }
        }

    };
    operation.allowsCellularAccess = YES;
    [[iCloudKitManager privateCloudDatabase] addOperation:operation];
}
Fetching Changed Data from Cloudkit Server
 
 
Q