قالب وردپرس درنا توس
Home / IOS Development / ios – Runs a CKFetchRecordsOperation while in UIApplicationStateBackground

ios – Runs a CKFetchRecordsOperation while in UIApplicationStateBackground



My app is configured to receive CloudKit remote alerts. Sometimes it receives these alerts while it is running in the background. I have not done anything about these alerts yet – I've simply passed UIBackgroundFetchResultNewData to the finisher. The reason is that I did not think I could only download from CloudKit in the background – I thought it could only be done via Background Retrieval or set up a special job to run in the background. But I'm looking at this now and I'm seeing running CKFetchRecordsOperation and downloading the related CKAsset file while it's in UIApplicationStateBackground actually seems to work.

So my current code is this:

  - (invalid) application: (UIApplication *) Application didReceiveRemoteNotification: (NSDictionary *) userInfo fetchCompletionHandler: (void (^) (UIBackgroundFetchResult)) completionHandler {

__ENTERING_METHOD__
CKNotification * ckNotification = [CKNotification notificationFromRemoteNotificationDictionary:userInfo];
if (ckNotification) {
if ([ckNotification.subscriptionID isEqualToString:kCKDocumentChangeSubscription]) {
CKRecordID * recordID = [(CKQueryNotification*)ckNotification recordID];
if (recordID) {
if ([UIApplication sharedApplication] .applicationState == UIApplicationStateBackground) {

if (finisher) {
completionHandler (UIBackgroundFetchResultNewData);
}
}
otherwise {
CKFetchRecordsOperation * fetchRecordsOperation = [[CKFetchRecordsOperation alloc] initWithRecordIDs: @ [recordID]];
fetchRecordsOperation.fetchRecordsCompletionBlock = ^ (NSDictionary * recordsByRecordID, NSError * Error) {

if (incorrect) {
dispatch_async (dispatch_get_main_queue (), ^ {
if (finisher) {
completionHandler (UIBackgroundFetchResultFailed);
}
});
}
otherwise {
CKRecord * ckDocumentRecord = recordsByRecordID [recordID];
CKAsset * documentAsset = [ckDocumentRecord objectForKey:ckDocumentAsset];
NSData * data = [NSData dataWithContentsOfURL:documentAsset.fileURL];
[self handleData:data];

UIBackgroundFetchResult result = (data == nil)? UIBackgroundFetchResultFailed: UIBackgroundFetchResultNewData;
if (completion) {
completion (result);
}
}

};
CKContainer * defaultContainer = [CKContainer defaultContainer];
CKDatabase * publicDatabase = [defaultContainer publicCloudDatabase];
[publicDatabase addOperation:fetchRecordsOperation];
}
}
otherwise {
if (finisher) {
completionHandler (UIBackgroundFetchResultFailed);
}
}
}
otherwise {
if (finisher) {
completionHandler (UIBackgroundFetchResultNoData);
}
}
}
otherwise {
if (finisher) {
completionHandler (UIBackgroundFetchResultNoData);
}
}
}

And I want this code to be this:

  - (invalid) application: (UIApplication *) application didReceiveRemoteNotification: (NSDictionary *) userInfo fetchCompletionHandler: (void (^) (UIBackgroundFetchResult)) completionHandler {

__ENTERING_METHOD__
CKNotification * ckNotification = [CKNotification notificationFromRemoteNotificationDictionary:userInfo];
if (ckNotification) {
if ([ckNotification.subscriptionID isEqualToString:kCKDocumentChangeSubscription]) {
CKRecordID * recordID = [(CKQueryNotification*)ckNotification recordID];
if (recordID) {
CKFetchRecordsOperation * fetchRecordsOperation = [[CKFetchRecordsOperation alloc] initWithRecordIDs: @ [recordID]];
fetchRecordsOperation.fetchRecordsCompletionBlock = ^ (NSDictionary * recordsByRecordID, NSError * Error) {

if (incorrect) {
dispatch_async (dispatch_get_main_queue (), ^ {
if (finisher) {
completionHandler (UIBackgroundFetchResultFailed);
}
});
}
otherwise {
CKRecord * ckDocumentRecord = recordsByRecordID [recordID];
CKAsset * documentAsset = [ckDocumentRecord objectForKey:ckDocumentAsset];
NSData * data = [NSData dataWithContentsOfURL:documentAsset.fileURL];
[self handleData:data];

UIBackgroundFetchResult result = (data == nil)? UIBackgroundFetchResultFailed: UIBackgroundFetchResultNewData;
if (completion) {
completion (result);
}
}

};
CKContainer * defaultContainer = [CKContainer defaultContainer];
CKDatabase * publicDatabase = [defaultContainer publicCloudDatabase];
[publicDatabase addOperation:fetchRecordsOperation];
}
otherwise {
if (finisher) {
completionHandler (UIBackgroundFetchResultFailed);
}
}
}
otherwise {
if (finisher) {
completionHandler (UIBackgroundFetchResultNoData);
}
}
}
otherwise {
if (finisher) {
completionHandler (UIBackgroundFetchResultNoData);
}
}
}

Runs a CKFetchRecordsOperation and downloads the related CKAsset file while it is in the background, which violates what can (or SHALL) be done in the background?


Source link