I have two icloud accounts (A and B) on two different devices. From one of them (A) I share ckrecord to another one (B) like this:
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)
When second device (B) did accept cloudkit share I fetch record and subscribe for changes:
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)
}
Now from device A I sucessfully (I am sure about that, changes is saved in iCloud) perform an update on a record shared with others. But device B doesnt know about that, unless I fetch record manually once again.
But from the other side, it works pretty well.
If I successfully perform an update on a record shared with me (on device B) then device A mnagically gets a notification about change and everything is fine. What makes the difference?
How to subscribe for changes on a records shared with me?
P.S when I will be able I will start a bount of 200 or even more for someone who will help me with this.
iOS 11, Swift 4, Xcode 9
Here's my checklist for debugging subscription notifications not appearing as expected. Sounds like you may have ruled some of these out already.
fetchAllSubscriptionsWithCompletionHandler
and NSLog each sub's details (especially: subscriptionID, trigger options, record type and the predicate). Verify that the expected subs exist. Verify that each sub's predicate matches expectations (in this case, compare the predicates you find on both devices).I wasted a bunch of time debugging "missing" notifications when:
So far, these four debugging steps have helped me understand all of my "missing notification" problems. Once I understood why the notifs didn't appear, that narrowed down which block of code was responsible.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With