Как получать уведомления об облачных уведомлениях об изменениях, сделанных в записи, которые мне поделились?

У меня есть две учетные записи icloud (A и B) на двух разных устройствах. Из одного из них ( A) я разделяю ckrecord на другой ( B) следующим образом:

let controller = UICloudSharingController { controller, preparationCompletionHandler in

    let share = CKShare(rootRecord: record)
    share[CKShareTitleKey] = "title" as CKRecordValue

    share[CKShareTypeKey] = "pl.blueworld.fieldservice" as CKRecordValue
    share.publicPermission = .readWrite

    let modifyOperation = CKModifyRecordsOperation(recordsToSave: [record, share], recordIDsToDelete: nil)
    modifyOperation.savePolicy = .ifServerRecordUnchanged
    modifyOperation.perRecordCompletionBlock = { record, error in
        print(error?.localizedDescription ?? "")
    }

    modifyOperation.modifyRecordsCompletionBlock = { records, recordIds, error in

        print(share.url)
        preparationCompletionHandler(share, CloudAssistant.shared.container, error)
    }

    CloudAssistant.shared.container.privateCloudDatabase.add(modifyOperation)
}

controller.delegate = self

UIViewController.top()?.present(controller, animated: true)

Когда второе устройство (B) принимало sharekit share, я получаю запись и подписываюсь на изменения:

func application(_ application: UIApplication, userDidAcceptCloudKitShareWith cloudKitShareMetadata: CKShareMetadata) {

    let acceptSharesOperation = CKAcceptSharesOperation(shareMetadatas: [cloudKitShareMetadata])
    acceptSharesOperation.perShareCompletionBlock = { metadata, share, error in

        if let error = error {
            UIAlertController.show(withMessage: error.localizedDescription)
        } else {

            let operation = CKFetchRecordsOperation(recordIDs: [cloudKitShareMetadata.rootRecordID])
            operation.perRecordCompletionBlock = { record, _, error in

                if let error = error {
                    UIAlertController.show(withMessage: error.localizedDescription)
                } else if let record = record {
                    CloudAssistant.shared.save(records: [record], recordIDsToDelete: [])

                    let options: CKQuerySubscriptionOptions = [.firesOnRecordCreation, .firesOnRecordUpdate, .firesOnRecordDeletion]
                    let territorySubscription = CKQuerySubscription(recordType: "Territory", predicate: NSPredicate(value: true), options: options)

                    let notificationInfo = CKNotificationInfo()
                    notificationInfo.shouldBadge = false
                    notificationInfo.shouldSendContentAvailable = true

                    territorySubscription.notificationInfo = notificationInfo

                    CloudAssistant.shared.sharedDatabase?.save(territorySubscription) { _, _ in }
                }
            }

            CloudAssistant.shared.container.sharedCloudDatabase.add(operation)
        }
    }
    acceptSharesOperation.qualityOfService = .userInteractive
    CKContainer(identifier: cloudKitShareMetadata.containerIdentifier).add(acceptSharesOperation)
}

Теперь с устройства A я успешно (я уверен, что изменения сохранены в iCloud) выполняют обновление записи, совместно используемой другими. Но устройство B не знает об этом, если я снова не сделаю запись вручную.

Но с другой стороны, он работает очень хорошо.

Если я успешно выполнил обновление для записи, совместно используемой мной (на устройстве B), тогда устройство A получает mnagically уведомление об изменениях, и все в порядке. В чем разница?

Как подписаться на изменения в общедоступных записях?

P.S, когда я смогу, я заработаю 200 или даже больше для тех, кто поможет мне в этом.

iOS 11, Swift 4, Xcode 9

Ответ 1

Здесь мой контрольный список для отладки уведомлений о подписке не отображается так, как ожидалось. Похоже, что вы, возможно, уже приняли некоторые из них.

  • Убедитесь, что приложение зарегистрировано для уведомлений
  • Убедитесь, что на устройстве для этого приложения включены уведомления.
  • Убедитесь, что все устройства используют один и тот же контейнер
  • При следующем запуске приложения прочитайте все подписки, используя fetchAllSubscriptionsWithCompletionHandler и NSLog для каждой дополнительной детали (особенно: идентификатор подписки, параметры триггера, тип записи и предикат). Убедитесь, что ожидаемые сущности существуют. Убедитесь, что каждый дополнительный предикат соответствует ожиданиям (в этом случае сравните предикаты, которые вы найдете на обоих устройствах).

Я потратил кучу времени на отладку "отсутствующих" уведомлений, когда:

  • Моя локальная версия использовала среду TEST, и пользователи TestFlight обращались к среде PROD. Этап отладки 2 нашел это.
  • При непреднамеренном повторном использовании идентификатора подписки, таким образом, каждый новый подзаголовок был перезаписан ранее. Шаг 4 отладки в конечном итоге выявил проблему.

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