Usually, when you call fetchRecordZoneChanges with the previous change token, you get a list of the record ID’s that have been deleted since your last fetch.
But if you get a changeTokenExpired error because it‘s been too long since you last fetched, you have to call fetch again without a token.
For my specific application, I still need to know, though, if any records have been deleted since my last sync. How can I get that information if I no longer have a valid change token?
iCloud & Data
RSS for tagLearn how to integrate your app with iCloud and data frameworks for effective data storage
Selecting any option will automatically load the page
Post
Replies
Boosts
Views
Activity
I work on an app that saves data to the Documents folder in the users iCloud Drive. This uses the iCloud -> iCloud Documents capability with a standard container.
We've noticed an issue where a user will delete the apps data by doing to Settings > {Name} > iCloud > Storage > App Name > select "delete data from iCloud", and then our app can no longer write to or create the Documents folder.
Once that happens, we get this error:
Error Domain=NSCocoaErrorDomain Code=513 "You don't have permission to save the file "Documents" in the folder "iCloud~your~bundle~identifier"." UserInfo={NSFilePath=/private/var/mobile/Library/Mobile Documents/iCloud~your~bundle~identifier/Documents, NSURL=file:///private/var/mobile/Library/Mobile%20Documents/iCloud~your~bundle~identifier/Documents, NSUnderlyingError=0x1102c7ea0 {Error Domain=NSPOSIXErrorDomain Code=13 "Permission denied"}}
This is reproducible using the sample project here https://developer.apple.com/documentation/uikit/synchronizing-documents-in-the-icloud-environment.
Steps to reproduce in that project:
Tap the plus sign in the top right corner to create a new document
Add a document name and tap "Save to Documents"
Go to Settings > {Name} > iCloud > Storage > SimpleiCloudDocument App Name > select "delete data from iCloud"
Reopen the app and repeat steps 1-2
Observe error on MainViewController+Document.swift:59
Deleting and reinstalling the app doesn't seem to help.
Topic:
App & System Services
SubTopic:
iCloud & Data
Hi all,
In my SwiftUI / SwiftData / Cloudkit app which is a series of lists, I have a model object called Project which contains an array of model objects called subprojects:
final class Project1
{
var name: String = ""
@Relationship(deleteRule: .cascade, inverse: \Subproject.project) var subprojects : [Subproject]?
init(name: String)
{
self.name = name
self.subprojects = []
}
}
The user will select a project from a list, which will generate a list of subprojects in another list, and if they select a subproject, it will generate a list categories and if the user selects a category it will generate another list of child objects owned by category and on and on.
This is the pattern in my app, I'm constantly passing arrays of model objects that are the children of other model objects throughout the program, and I need the user to be able to add and remove things from them.
My initial approach was to pass these arrays as bindings so that I'd be able to mutate them. This worked for the most part but there were two problems: it was a lot of custom binding code and when I had to unwrap these bindings using init?(_ base: Binding<Value?>), my program would crash if one of these arrays became nil (it's some weird quirk of that init that I don't understand at al).
As I'm still learning the framework, I had not realized that the @model macro had automatically made my model objects observable, so I decided to remove the bindings and simply pass the arrays by reference, and while it seems these references will carry the most up to date version of the array, you cannot mutate them unless you have access to the parent and mutate it like such:
project.subcategories?.removeAll { $0 == subcategory }
project.subcategories?.append(subcategory)
This is weirding me out because you can't unwrap subcategories before you try to mutate the array, it has to be done like above. In my code, I like to unwrap all optionals at the moment that I need the values stored in them and if not, I like to post an error to the user. Isn't that the point of optionals? So I don't understand why it's like this and ultimately am wondering if I'm using the correct design pattern for what I'm trying to accomplish or if I'm missing something? Any input would be much appreciated!
Also, I do have a small MRE project if the explanation above wasn't clear enough, but I was unable to paste in here (too long), attach the zip or paste a link to Google Drive. Open to sharing it if anyone can tell me the best way to do so. Thanks!
I'm experiencing a persistent issue with CloudKit sharing in my iOS application. When attempting to present a UICloudSharingController, I receive the error message "Unknown client: ChoreOrganizer" in the console.
App Configuration Details:
App Name: ChoreOrganizer
Bundle ID: com.ProgressByBits.ChoreOrganizer
CloudKit Container ID: iCloud.com.ProgressByBits.ChoreOrganizer
Core Data Model Name: ChoreOrganizer.xcdatamodeld
Core Data Entity: Chore
Error Details:
The error "Unknown client: ChoreOrganizer" occurs when I present the UICloudSharingController
This happens only on the first attempt to share; subsequent attempts during the same app session don't show the error but sharing still doesn't work
All my code executes successfully without errors until UICloudSharingController is presented
Implementation Details:
I'm using NSPersistentCloudKitContainer for Core Data synchronization and UICloudSharingController for sharing. My implementation creates a custom CloudKit zone, saves both a record and a CKShare in that zone, and then presents the sharing controller.
Here's the relevant code:
@MainActor
func presentSharing(from viewController: UIViewController) async throws {
// Create CloudKit container
let container = CKContainer(identifier: containerIdentifier)
let database = container.privateCloudDatabase
// Define custom zone ID
let zoneID = CKRecordZone.ID(zoneName: "SharedChores", ownerName: CKCurrentUserDefaultName)
do {
// Check if zone exists, create if necessary
do {
_ = try await database.recordZone(for: zoneID)
} catch {
let newZone = CKRecordZone(zoneID: zoneID)
_ = try await database.save(newZone)
}
// Create record in custom zone
let recordID = CKRecord.ID(recordName: "SharedChoresRoot", zoneID: zoneID)
let rootRecord = CKRecord(recordType: "ChoreRoot", recordID: recordID)
rootRecord["name"] = "Shared Chores Root" as CKRecordValue
// Create share
let share = CKShare(rootRecord: rootRecord)
share[CKShare.SystemFieldKey.title] = "Shared Tasks" as CKRecordValue
// Save both record and share in same operation
let recordsToSave: [CKRecord] = [rootRecord, share]
_ = try await database.modifyRecords(saving: recordsToSave, deleting: [])
// Present sharing controller
let sharingController = UICloudSharingController(share: share, container: container)
sharingController.delegate = shareDelegate
// Configure popover
if let popover = sharingController.popoverPresentationController {
popover.sourceView = viewController.view
popover.sourceRect = CGRect(
x: viewController.view.bounds.midX,
y: viewController.view.bounds.midY,
width: 1, height: 1
)
popover.permittedArrowDirections = []
}
viewController.present(sharingController, animated: true)
} catch {
throw error
}
}
Steps I've already tried:
Verified correct bundle ID and container ID match in all places (code, entitlements file, Developer Portal)
Added NSUbiquitousContainers configuration to Info.plist
Ensured proper entitlements in the app
Created and configured proper provisioning profiles
Tried both default zone and custom zone for sharing
Various ways of saving the record and share (separate operations, same operation)
Cleaned build folder, deleted derived data, reinstalled the app
Tried on both simulator and physical device
Confirmed CloudKit container exists in CloudKit Dashboard with correct schema
Verified iCloud is properly signed in on test devices
Console Output:
1. Starting sharing process
2. Created CKContainer with ID: iCloud.com.ProgressByBits.ChoreOrganizer
3. Using zone: SharedChores
4. Checking if zone exists
5. Zone exists
7. Created record with ID: <CKRecordID: 0x3033ebd80; recordName=SharedChoresRoot, zoneID=SharedChores:__defaultOwner__>
8. Created share with ID: <CKRecordID: 0x3033ea920; recordName=Share-C4701F43-7591-4436-BBF4-6FA8AF3DF532, zoneID=SharedChores:__defaultOwner__>
9. About to save record and share
10. Records saved successfully
11. Creating UICloudSharingController
12. About to present UICloudSharingController
13. UICloudSharingController presented
Unknown client: ChoreOrganizer
Additional Information:
When accessing the CloudKit Dashboard, I can see that data is being properly synced to the cloud, indicating that the basic CloudKit integration is working. The issue appears to be specific to the sharing functionality.
I would greatly appreciate any insights or solutions to resolve this persistent "Unknown client" error. Thank you for your assistance.
I have a UIKit app where I've adopted SwiftData and I'm struggling with a crash coming in from some of my users. I'm not able to reproduce it myself and as it only happens to a small fraction of my user base, it seems like a race condition of some sort.
This is the assertion message:
SwiftData/DefaultStore.swift:453: Fatal error: API Contract Violation: Editors must register their identifiers before invoking operations on this store SwiftData.DefaultStore: 00CF060A-291A-4E79-BEC3-E6A6B20F345E did not. (ID is unique per crash)
This is the ModelActor that crashes:
@available(iOS 17, *)
@ModelActor
actor ConsumptionDatabaseStorage: ConsumptionSessionStorage {
struct Error: LocalizedError {
var errorDescription: String?
}
private let sortDescriptor = [SortDescriptor(\SDConsumptionSession.startTimeUtc, order: .reverse)]
static func createStorage(userId: String) throws -> ConsumptionDatabaseStorage {
guard let appGroupContainer = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: UserDefaults.defaultAppGroupIdentifier) else {
throw Error(errorDescription: "Invalid app group container ID")
}
func createModelContainer(databaseUrl: URL) throws -> ModelContainer {
return try ModelContainer(for: SDConsumptionSession.self, SDPriceSegment.self, configurations: ModelConfiguration(url: databaseUrl))
}
let databaseUrl = appGroupContainer.appendingPathComponent("\(userId).sqlite")
do {
return self.init(modelContainer: try createModelContainer(databaseUrl: databaseUrl))
} catch {
// Creating the model storage failed. Remove the database file and try again.
try? FileManager.default.removeItem(at: databaseUrl)
return self.init(modelContainer: try createModelContainer(databaseUrl: databaseUrl))
}
}
func isStorageEmpty() async -> Bool {
(try? self.modelContext.fetchCount(FetchDescriptor<SDConsumptionSession>())) ?? 0 == 0 // <-- Crash here!
}
func sessionsIn(interval: DateInterval) async throws -> [ConsumptionSession] {
let fetchDescriptor = FetchDescriptor(predicate: #Predicate<SDConsumptionSession> { sdSession in
if let startDate = sdSession.startTimeUtc {
return interval.start <= startDate && interval.end > startDate
} else {
return false
}
}, sortBy: self.sortDescriptor)
let consumptionSessions = try self.modelContext.fetch(fetchDescriptor) // <-- Crash here!
return consumptionSessions.map { ConsumptionSession(swiftDataSession: $0) }
}
func updateSessions(sessions: [ConsumptionSession]) async throws {
if #unavailable(iOS 18) {
// Price segments are duplicated if re-inserted so unfortunately we have to delete and reinsert sessions.
// On iOS 18, this is enforced by the #Unique macro on SDPriceSegment.
let sessionIds = Set(sessions.map(\.id))
try self.modelContext.delete(model: SDConsumptionSession.self, where: #Predicate<SDConsumptionSession> {
sessionIds.contains($0.id)
})
}
for session in sessions {
self.modelContext.insert(SDConsumptionSession(consumptionSession: session))
}
if self.modelContext.hasChanges {
try self.modelContext.save()
}
}
func deleteAllSessions() async {
if #available(iOS 18, *) {
try? self.modelContainer.erase()
} else {
self.modelContainer.deleteAllData()
}
}
}
The actor conforms to this protocol:
protocol ConsumptionSessionStorage {
func isStorageEmpty() async -> Bool
func hasCreditCardSessions() async -> Bool
func sessionsIn(interval: DateInterval) async throws -> [ConsumptionSession]
func updateSessions(sessions: [ConsumptionSession]) async throws
func deleteAllSessions() async
}
The crash is coming in from line 30 and 41, in other words, when trying to fetch data from the database. There doesn't seem to be any common trait for the crashes. They occur across iOS versions and device types.
Any idea what might cause this?
I'm getting the following error message when executing the rollback method in a modelContext, what could be causing this ?
SwiftData/ModelSnapshot.swift:46: Fatal error: A ModelSnapshot must be initialized with a known-keys dictionary
The 'unique' attribute is a really nice feature, BUT. In some of my apps, the unique identifier for an object is a combination of multiple attributes. (Example: a book title is not unique, but a combination of book title and author list is.)
How do I model this with SwiftData? I cannot use @Attribute(.unique) on either the title OR the author list, but I want SwiftData to provide the same "insert or update" logic.
Is this possible?
How does SwiftData work with background operations? CoreData had background context that could be used to avoid UI hang for heavy operations.
Is there an equivalent in SwiftData, and if so, do I have to merge changes or does it save directly to persistent store?
I have an issue in my app, where the crashing frame is an assertionFailure in BackingData.set inside SwiftData framework. My own app doesn't appear until frame 14. I have no idea what causes this, or even how to create a reproducible project as this only happens on some devices.
The frame prior to the assertionFailure is this:
#1 (null) in BackingData.set(any:value:) ()
It seems like there is a backing data encoding happening in my Model class, and some value is causing it to fail. The model being accessed is through a relationship, and the frame in the app crashing is along the lines of
Text(parent.child.name)
Obviously, something is wrong in how I have made child, but the part that stand out to me is the assertionFailure in a release build
I have implemented CKSyncEngine synchronization, and it works well. I can update data on one device and see the changes propagate to another device quickly. However, the initial sync when a user downloads the app on a new device is a significant issue for both me and my users.
One problem is that the sync engine fetches deletion events from the server. On a new device, the local database is empty, so these deletions are essentially no-ops. This would not be a big problem if there were only a few records or if it was fast. I measured the initial sync and found that there are 150 modified records and 62,168 deletions. Counting these alone takes over five minutes, even without processing them. The deletions do nothing because the local database has nothing to delete, yet they still add a significant delay.
I understand that the sync engine ensures consistency across all devices, but five minutes of waiting with the app open just to insert a small number of records is excessive. The problem would be worse if there were tens of thousands of new records to insert, since downloading and saving the data would take even longer.
This leads to a poor user experience. Users open the app and see data being populated for several minutes, or they are stuck on a screen that says the data is being synchronized with iCloud.
I am wondering if there is a way to make the sync engine ignore deletion events when the state serialization is nil. Alternatively, is there a recommended method for handling initial synchronization more efficiently?
One idea I considered is storing all the data as a backup in iCloud Documents, along with the state serialization at that point in time. When a user opens the app for the first time, I could download the file, extract the data, and set the state serialization to the saved value. I am not sure if this would work. I do not know if state serialization is tied to the device or if it only represents the point where the sync engine left off. My guess is that it might reference some local device storage.
I am not sure what else to try. I could fetch all data using CloudKit, create the sync engine with an empty state serialization, and let it fetch everything again, but that would still take a long time.
My records are very small, mostly a date when something happened and an ID referencing the parent. Since the app tracks watched episodes, I only store the date the user watched the episode and the ID of that episode.
Hello,
I recently published an app that uses Swift Data as its primary data storage. The app uses concurrency, background threads, async await, and BLE communication.
Sadly, I see my app incurs many fringe crashes, involving EXC_BAD_ACCESS, KERN_INVALID_ADDRESS, EXC_BREAKPOINT, etc.
I followed these guidelines:
One ModelContainer that is stored as a global variable and used throughout.
ModelContexts are created separately for each task, changes are saved manually, and models are not passed around.
Threads with different ModelContexts might manipulate and/or read the same data simultaneously.
I was under the impression this meets the usage requirements.
I suspect perhaps the issue lies in my usage of contexts in a single await function, that might be paused and resumed on a different thread (although same execution path). Is that the case? If so, how should SwiftData be used in async scopes?
Is there anything else particularly wrong in my approach?
Exact same app works fine in debug builds, but on release builds I see this stacktrace indicating that assert() was hit.
Incident Identifier: ***
Distributor ID: com.apple.TestFlight
Hardware Model: iPhone14,3
Process: AuditOS [67847]
Path: /private/var/containers/Bundle/Application/***
Identifier: ***
Version: 1.0 (15)
AppStoreTools: 16C5031b
AppVariant: 1:iPhone14,3:18
Beta: YES
Code Type: ARM-64 (Native)
Role: Foreground
Parent Process: launchd [1]
Coalition: ***
Date/Time: 2025-02-11 12:37:54.7801 -0600
Launch Time: 2025-02-11 12:37:33.1737 -0600
OS Version: iPhone OS 18.3 (22D63)
Release Type: User
Baseband Version: 4.20.03
Report Version: 104
Exception Type: EXC_BREAKPOINT (SIGTRAP)
Exception Codes: 0x0000000000000001, 0x000000019d388e2c
Termination Reason: SIGNAL 5 Trace/BPT trap: 5
Terminating Process: exc handler [67847]
Triggered by Thread: 0
Thread 0 Crashed:
0 libswiftCore.dylib 0x000000019d388e2c _assertionFailure(_:_:file:line:flags:) + 264 (AssertCommon.swift:147)
1 SwiftData 0x0000000261842e04 Schema.KeyPathCache.validateAndCache(keypath:on:) + 2628 (Schema.swift:0)
2 SwiftData 0x000000026178cac4 static PersistentModel.keyPathToString(keypath:) + 360 (DataUtilities.swift:36)
3 SwiftData 0x000000026184c9e4 static PersistentModel.fetchDescriptorKeyPathString(for:) + 36 (FetchDescriptor.swift:51)
4 SwiftData 0x00000002617b9770 closure #1 in PredicateExpressions.KeyPath.convert(state:) + 172 (FetchDescriptor.swift:458)
5 SwiftData 0x00000002617b7f48 PredicateExpressions.KeyPath.convert(state:) + 352 (FetchDescriptor.swift:438)
6 SwiftData 0x00000002617bb7ec protocol witness for ConvertibleExpression.convert(state:) in conformance PredicateExpressions.KeyPath<A, B> + 16 (<compiler-generated>:0)
7 SwiftData 0x00000002617baaa0 PredicateExpression.convertToExpressionOrPredicate(state:) + 716 (FetchDescriptor.swift:219)
8 SwiftData 0x00000002617ba6dc PredicateExpression.convertToExpression(state:) + 32 (FetchDescriptor.swift:237)
9 SwiftData 0x00000002617b7cfc PredicateExpressions.Equal.convert(state:) + 328 (:-1)
10 SwiftData 0x00000002617bba08 protocol witness for ConvertibleExpression.convert(state:) in conformance PredicateExpressions.Equal<A, B> + 64 (<compiler-generated>:0)
11 SwiftData 0x00000002617baaa0 PredicateExpression.convertToExpressionOrPredicate(state:) + 716 (FetchDescriptor.swift:219)
12 SwiftData 0x00000002617b7abc PredicateExpression.convertToPredicate(state:) + 28 (FetchDescriptor.swift:244)
13 SwiftData 0x00000002617b7190 nsFetchRequest<A>(for:in:) + 1204 (FetchDescriptor.swift:64)
14 SwiftData 0x0000000261783358 DefaultStore.fetch<A>(_:) + 292 (DefaultStore.swift:496)
15 SwiftData 0x000000026178322c protocol witness for DataStore.fetch<A>(_:) in conformance DefaultStore + 16 (<compiler-generated>:0)
16 SwiftData 0x00000002617847fc asDataStore #1 <A><A1>(_:) in closure #1 in ModelContext.fetch<A>(_:) + 3152 (ModelContext.swift:2590)
17 SwiftData 0x00000002617a74d8 partial apply for closure #1 in ModelContext.fetch<A>(_:) + 100 (<compiler-generated>:0)
18 SwiftData 0x00000002617a7438 closure #1 in ModelContext.enumerateFetchableStores<A>(_:_:) + 208 (ModelContext.swift:2527)
19 SwiftData 0x00000002617a731c specialized ModelContext.enumerateFetchableStores<A>(_:_:) + 200 (ModelContext.swift:2522)
20 SwiftData 0x00000002617a6f08 ModelContext.fetch<A>(_:) + 144 (ModelContext.swift:2534)
21 SwiftData 0x00000002617a6e70 dispatch thunk of ModelContext.fetch<A>(_:) + 56 (:-1)
22 AuditOS 0x00000001041af3f4 0x10419c000 + 78836
23 AuditOS 0x00000001041bebd5 0x10419c000 + 142293
24 AuditOS 0x00000001041bbbf5 0x10419c000 + 130037
25 AuditOS 0x00000001041d8be5 0x10419c000 + 248805
26 AuditOS 0x00000001041bde6d 0x10419c000 + 138861
27 libswift_Concurrency.dylib 0x00000001aa6bfe39 completeTaskWithClosure(swift::AsyncContext*, swift::SwiftError*) + 1 (Task.cpp:497)
The code in question looks like this:
func addRecord<T: MyDtoProtocol>(_ someDTO: T) async throws {
var zone: ZoneModel? = nil
let recordName = someDTO.recordNameType
let fetchDescriptor = FetchDescriptor<T.ModelType> (predicate: #Predicate {$0.recordName == recordName})
> var localEntitites: [T.ModelType] = try modelContext.fetch(fetchDescriptor) <---- I have isolated crash to this line.
Basically for each swiftdata model type I have associatedType for Data Transfer Object type and vice versa.
I have an image field on a Core Data entity with "Allows External Storage" enabled. When I delete a record, the external binary data file remains on disk. How can I ensure that all externally stored data is deleted along with the record?
Is it possible to track history using the new HistoryDescriptor feature in SwiftData? Or can I only get the current most recent data? Or is it possible to output the changed data itself, along with timestamps?
I am hoping that it is possible to track by a standard feature like NSPersistentHistoryTransaction in CoreData.
Do we still have to use a method in SwiftData that creates more tracking data itself?
Apple WTF? What did you do to all my Apps? none of them work in iOS26.1 (all worked in 26.0).
XCode simply says:
CoreData: error: addPersistentStoreWithType:configuration:URL:options:error: returned error NSCocoaErrorDomain (134140) *
SwiftData is supposed to do all these automatically 🤷🏻
Hello everyone,
I'm trying to adopt the new Staged Migrations for Core Data and I keep running into an error that I haven't been able to resolve.
The error messages are as follows:
warning: Multiple NSEntityDescriptions claim the NSManagedObject subclass 'Movie' so +entity is unable to disambiguate.
warning: 'Movie' (0x60000350d6b0) from NSManagedObjectModel (0x60000213a8a0) claims 'Movie'.
error: +[Movie entity] Failed to find a unique match for an NSEntityDescription to a managed object subclass
This happens for all of my entities when they are added/fetched. Movie is an abstract entity subclass, and it has the error error: +[Movie entity] Failed to find which is unique to the subclass entities, but this occurs for all entities.
The NSPersistentContainer is loaded only once, and I set the following option after it's loaded:
storeDescription.setOption(
[stages],
forKey: NSPersistentStoreStagedMigrationManagerOptionKey
)
The warnings and errors only appear after I fetch or save to context. It happens regardless of whether the database was migrated or not. In my test project, using the generic NSManagedObject with NSEntityDescription.insertNewObject(forEntityName: "MyEntity", into: context) does not cause the issue. However, using the generic NSManagedObject is not a viable option for my app.
Setting the module to "Current Project Module" doesn't change anything, except that it now prints "claims 'MyModule.Show'" in the warnings. I have verified that there are no other entities with the same name or renameIdentifier.
Has anyone else encountered this issue, or can offer any suggestions on how to resolve it?
Thanks in advance for any help!
I have a total of 100 asset packs associated with my app but I have archived 5 of them. Unfortunately I am now unable to upload any more asset packs (the reported error is "backgroundAsset limit reached -- This app has already reached the maximum number of active backgroundAssets. Maximum allowed is 100.") I assumed that archiving asset packs would make them inactive (and thus not count against the limit). This seems to not be the case and I'm not sure how I can upload new asset packs.
relationshipKeyPathsForPrefetching in SwiftData does not seem to work here when scrolling down the list. Why?
I would like all categories to be fetched while posts are fetched - not while scrolling down the list.
struct ContentView: View {
var body: some View {
QueryList(
fetchDescriptor: withCategoriesFetchDescriptor
)
}
var withCategoriesFetchDescriptor: FetchDescriptor<Post> {
var fetchDescriptor = FetchDescriptor<Post>()
fetchDescriptor.relationshipKeyPathsForPrefetching = [\.category]
return fetchDescriptor
}
}
struct QueryList: View {
@Query
var posts: [Post]
init(fetchDescriptor: FetchDescriptor<Post>) {
_posts = Query(fetchDescriptor)
}
var body: some View {
List(posts) { post in
VStack {
Text(post.title)
Text(post.category?.name ?? "")
.font(.footnote)
}
}
}
}
@Model
final class Post {
var title: String
var category: Category?
init(title: String) {
self.title = title
}
}
@Model final class Category {
var name: String
init(name: String) {
self.name = name
}
}
After Xcode 26.1 was updated and installing the OS 26.1 simulators, my app started crashing related to transformable properties. When I checked my schema, I noticed that properties with array collection types are suddenly set with an option transformable with Optional("NSSecureUnarchiveFromData")], even though I do not use any transformable types. I verified the macros, no transformable was specified. This is causing ModelCoders to encode/decode my properties incorrectly.
This is not an issue when I switch back to OS 26.0 simulators.
Hi everyone,
I’m currently developing a SwiftUI app that uses SwiftData with CloudKit sharing enabled. The app works fine on my own Apple ID, and local syncing with iCloud is functioning correctly — but sharing with other Apple IDs consistently fails.
Setup:
SwiftUI + SwiftData using a ModelContainer with .shared configuration
Sharing UI is handled via UICloudSharingController
iCloud container: iCloud.com.de.SkerskiDev.FoodGuard
Proper entitlements enabled (com.apple.developer.icloud-services, CloudKit, com.apple.developer.coredata.cloudkit.containers, etc.)
Automatic provisioning profiles created by Xcode
Error:<CKError 0x1143a2be0: "Bad Container" (5/1014);
"Couldn't get container configuration from the server for container iCloud.com.de.SkerskiDev.FoodGuard">
What I’ve tried:
Verified the iCloud container is correctly created and enabled in the Apple Developer portal
Checked bundle identifier and container settings
Rebuilt and reinstalled the app
Ensured correct iCloud entitlements and signing capabilities
Questions:
Why does CloudKit reject the container for sharing while local syncing works fine?
Are there known issues with SwiftData .shared containers and multi-user sharing?
Are additional steps required (App Store Connect, privacy settings) to allow sharing with other Apple IDs?
Any advice, experience, or example projects would be greatly appreciated. 🙏
Thanks!
Sebastian