Мое приложение настроено для получения удаленных уведомлений CloudKit. Иногда он получает эти уведомления, пока работает в фоновом режиме. Я ничего еще не сделал с этими уведомлениями - я просто передал UIBackgroundFetchResultNewData обработчику завершения. Причина в том, что я не думал, что смогу просто загрузить из CloudKit в фоновом режиме - я думал, что это можно сделать только с помощью Background Fetch или настройки специальной работы для запуска в фоновом режиме. Но сейчас я возвращаюсь к этому и вижу, что запуск CKFetchRecordsOperation и загрузка соответствующего файла CKAsset в UIApplicationStateBackground действительно работает.
Итак, мой текущий код такой:
- (void)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 (completionHandler) {
completionHandler(UIBackgroundFetchResultNewData);
}
}
else {
CKFetchRecordsOperation *fetchRecordsOperation = [[CKFetchRecordsOperation alloc] initWithRecordIDs:@[recordID]];
fetchRecordsOperation.fetchRecordsCompletionBlock = ^(NSDictionary *recordsByRecordID, NSError *error) {
if (error) {
dispatch_async(dispatch_get_main_queue(), ^{
if (completionHandler) {
completionHandler(UIBackgroundFetchResultFailed);
}
});
}
else {
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];
}
}
else {
if (completionHandler) {
completionHandler(UIBackgroundFetchResultFailed);
}
}
}
else {
if (completionHandler) {
completionHandler(UIBackgroundFetchResultNoData);
}
}
}
else {
if (completionHandler) {
completionHandler(UIBackgroundFetchResultNoData);
}
}
}
И я хочу, чтобы этот код был таким:
- (void)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 (error) {
dispatch_async(dispatch_get_main_queue(), ^{
if (completionHandler) {
completionHandler(UIBackgroundFetchResultFailed);
}
});
}
else {
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];
}
else {
if (completionHandler) {
completionHandler(UIBackgroundFetchResultFailed);
}
}
}
else {
if (completionHandler) {
completionHandler(UIBackgroundFetchResultNoData);
}
}
}
else {
if (completionHandler) {
completionHandler(UIBackgroundFetchResultNoData);
}
}
}
Является ли выполнение CKFetchRecordsOperation и загрузка соответствующего файла CKAsset в фоновом режиме каким-либо нарушением того, что можно (или СЛЕДУЕТ) делать в фоновом режиме?