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];
}