I’m working on an app that uses the new sharing support in iOS 15 using NSPersistentCloudKitContainer
. I do not see a way to tell Core Data that an object, or set of objects, is no longer shared.
For example, if I create a set of objects and then call share(_:to:completion:)
, the objects are shared properly and moved to a new, custom CKRecordZone
, as expected.
Now, if the user stops sharing an object using UICloudSharingController
, the CKShare
that Core Data created is properly deleted from CloudKit, but the objects are still in the custom zone, and Core Data still has the original CKShare
associated with those objects. So, when I call fetchShares(matching:)
, I still get the CKShare
, but of course, that is no longer valid. In the past, with my own code, I’d use UISharingController
s delegate to get notified that the user stopped sharing, and then update my model. But there doesn’t seem to be a way to tell Core Data about the change.
Forcing Core Data to fetch CloudKit changes by either moving the app to background and then foreground, or by stopping the app and relaunching does not cause Core Data to notice the change to the share.
Does anyone know how to tell Core Data that these objects are no longer shared?
Apple rolled out iOS 15 for everyone last week, bringing new features to make your daily routine easy. Among the new features that are available to you is ‘Shared With You’ – a new section that highlights content shared by others over the Messages app.
If you don’t want your iPhone’s Safari settings to sync over to other Apple devices, open Safari, scroll down to the bottom of the Start Page, and tap on Edit . Inside the Customize Start Page, turn off the Use Start Page on All Devices toggle to disable syncing through iCloud.
You can even choose to disable ‘Share With You’ completely, not just for Safari. For this, open the Settings app first. Then tap on Messages. Scroll down and tap on Shared with You. Now, turn off the Safari toggle. If you want to disable the ‘Shared With You’ feature completely, for all apps, then toggle off the Automatic Sharing option at the top.
If you have disabled Shared with You for Safari, a contact, or throughout iOS, but the section continues to show up or reappears after some time inside the app, then it may be happening because you have multiple Apple devices signed in to the same iCloud account.
I worked around this by always checking to see if the share actually exists in CloudKit, rather than relying on the existence of a CKShare
from fetchShares(matching:)
. I get the URL
from the CKShare
returned from fetchShares(matching:)
and call this:
private func remoteShare(at url: URL) async throws -> CKShare? {
do {
let metadata = try await cloudKitContainer.shareMetadata(for: url)
return metadata.share
} catch let error as CKError {
if error.retryable {
throw RemoteError.retryable
} else if error.userInterventionRequiredError {
throw RemoteError.userInterventionRequired
} else if error.code == .unknownItem {
return nil
} else {
throw RemoteError.remoteFailure
}
} catch {
throw RemoteError.remoteFailure
}
}
}
If I get unknownItem
that means there is no share on the remote, so the object is not actually shared.
The RemoteError
is my custom error handling, and I have some extensions on CKError
to categorize the errors.
Another workaround to the issue is to create a copy of the object being shared, and then deleting the original. It's not elegant, but it works in the meantime. (Hopefully Apple will address this at some point with a better solution.) The copy will be placed in the default zone like it was before you shared the original. You'll be left with an empty share zone, but I dealt with that by running a background task upon app launch that deletes all empty share zones, so it doesn't get out of hand.
I haven't tried the solution posted by Dharman, but I imagine it's slower than querying the local cache. Using the method above, you can still use the "isShared" code from the demo app.
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