In the summer, Apple published an informative sample app on sharing objects between iCloud users using Core Data, CloudKit and UICloudSharingController in SwiftUI.
However, adding more participants using UICloudSharingController does not appear to work when used for Core Data with CloudKit.
MRE:
See the Apple sample app linked above.
The same problem also appears when using other sample apps, like the one from RayW.
The problem does not appear in samples that use pure CloudKit, such as this one by Apple.
Reproduction:
- Create new share,
- Manage share with UICloudSharingController,
- Share With More People,
- Share using Messages or other service. Succeeds on first attempt, fails on subsequent attempts.
Expectation:
We can use UICloudSharingController to add new participants, using Messages, Mail or other platforms. The link will display correctly on all devices.
Reality:
On iOS16+, attempting to share via Messages engages the "Collaboration" framework and leads to an alert: "An Error Occurred. Unable to start collaboration" (see Image 1). A console warning appears (see below). Triggering this error breaks ANY further shares - the link now cannot be created for Mail and other platforms either (see Image 2). Furthermore, if the first attempt succeeds, the link does not appear correctly on the receiving device (see Image 3).
After further testing, UICloudSharingController also fails in iOS15 - it just dismisses the sheet rather than throw an alert on a compact device. UICloudSharingController is definitely bugged when showing an existing share.
Console logs:
The following console message appears when this issue happens for the first time:
- CoreDataCloudKitShare[3672:1242159] systemSharingUIDidSaveShareBlock received error: <CKError 0x28314d8c0: "Server Record Changed" (14/2004); server message = "client oplock error updating record"; op = 134D57570A63DF3A; uuid = 8F070F8B-0AC0-4FFE-A52D-154BCBF3196C; container ID = “containerID>
Where "containerID" is the CKContainer ID, like “iCloud.com.company.samples.CoreDataCloudKitShare”. The message does not appear on subsequent attempts to add more people.
Question:
How can this be resolved, so that we can share Core Data records between users using CloudKit and UICloudSharingController?
EDITs:
- Other samples of sharing using Core Data and CloudKit exhibit the same problem. Also, console shows a warning when the issue first happens. Post was edited to reflect this.
- Question was also posed in Apple Dev Forums
- Feedback submitted at FB11623246.
- Added conclusions after further testing
- 24 October 2022: I thought the issue was resolved in iOS16.0.3, but it continues to manifest. It does not matter whether UICloudSharingController is invoked using UIViewController or UIViewControllerRepresentable.
- 10 November 2022: The issue appears in both Development and Production environments (tested via TestFlight)
- 15 November 2022: In Ask Apple office hours, this was brought up to the attention of an Apple engineer, who confirmed this as a regression.
- 25 November 2022: A DTS has been opened. This is now confirmed as a known bug with high priority.
- 26 December 2022: The bug remains in iOS16.2. An attempt was made to use SWCollaborationView as an alternative to managing collaboration in iOS16. The sharing workflow indeed goes through even on subsequent shares. However, SWCollaborationView does not appear to be compatible with SwiftUI (ugh). See associated SO question
- 17 January 2023: SWCollaborationView is confirmed as NOT compatible with SwiftUI. FB submitted at FB11941664, please submit FB as well.
- 25 January 2023: Unfortunately, the issue persists in iOS 16.3.
- 15 February 2023: Unfortunately, the issue persists in iOS 16.3.1.
- 2 March 2023: Apple says the issue should be fixed in the following configuration. I have not yet tested this (maybe next week). If anyone could confirm it would be great.
- Xcode 14.3 beta 2 (14E5207e)
- iOS 16.4 beta 2 (20E5223e)
- iPadOS 16.4 beta 2 (20E5223e)
- macOS 13.3 beta 2 (22E5230e)
- 12 March 2023: I tested the above configuration. UICloudSharingController now works as intended. HOWEVER, attempting to add a photo to an existing share where user is Participant with Write privileges results in an error. Apple was notified, waiting for a response. Console output:
shareObject(_:to:completionHandler:): Failed to share an object: Error Domain=NSCocoaErrorDomain Code=134060 "A Core Data error occurred." UserInfo={NSLocalizedFailureReason=NSPersistentCloudKitContainer does not support sharing objects across persistent stores. Objects must first be assigned to the correct persistent store (private, or shared as the case may be), so that they can be moved in to the correct record zone for sharing.})
- 14 March 2023: I re-tested and confirmed the above issue using a fresh fork of the Apple Sample app. If you'd like to reproduce the issue, here are the steps I used
- 27 April 2023: After some back and forth with Apple, I managed to resolve the issues described in this post, and built a working app with Core Data and CloudKit sharing. On their side, Apple updated the sample app. Mission accomplished.
UICloudSharingController
usingUIViewController
andUIWindowScene
. Having discovered the bug, I tried re-implementingUICloudSharingController
usingUIViewRepresentable
. It made no difference. – NavicularpersistenceContainer.share([managedRootObject], to: nil)
moves the entire object graph to the shared store, if it isn't already present in it. You should be able to verify which store the object is being fetched/used from at runtime as well. "Objects must first be assigned to the correct persistent store (private, or shared as the case may be)" It's odd that the error mentions the private store here. – FrugNSPersistentCloudKitContainer
to log this error. Everything seems to just work. – Frug