Learn how to integrate your app with iCloud for effective data storage.

Documentation

Posts under iCloud subtopic

Post

Replies

Boosts

Views

Activity

CloudKit it writes to development container, not Production
I have an app that I signed and distribute between some internal testflight users. Potentially I want to invite some 'Public' beta testers which don't need to validate (_World have read rights in the public database) Question: Do I need to have a working public CloudKit , when users are invited through TestFlight, or are they going to test on the development container? I understand that when I invite beta-tester without authorization (external testers) they cannot access the developer container, so therefore I need to have the production CloudKit container up and running. I have tried to populate the public production container, but for whatever reason my upload app still goes to the development container. I have archived the app, and tried, but no luck. I let xcode manage my certificates/profiles. but what do I need to change to be able to use my upload file to upload the production container, instead of the development. I tried: init() { container = CKContainer(identifier: "iCloud.com.xxxx.xxxx") publicDB = container.publicCloudDatabase I got no error in the console, but data is always populated to the development database, instead the production. I tried to create a provisioning profile, but for some reason Xcode doesn't like it. Tried to create one a different provisioning profile manual through the developer portal, for the app. but xcode doesn't want to use that, and mentions that the requirement are already in place. What can I check/do to solve this.
1
0
204
Aug ’25
Unable to sync SwiftData model fully using CloudKit
Hey everyone I just ran into an issue where I couldn't sync the model below fully by using CloudKit, enum LinkMapV3_1: VersionedSchema { static let versionIdentifier: Schema.Version = .init(3, 1, 0) static var models: [any PersistentModel.Type] { [AnnotationData.self, GroupData.self, Item.self, Deployment.self, History.self] } // MARK: - Data @Model class AnnotationData { var name: String = "" var longitude: Double = 0.0 var latitude: Double = 0.0 var order: Int = -1 var level: Int = 1 var detail: String = "" @Relationship(deleteRule: .nullify, inverse: \GroupData.annotation) var groups: [GroupData]? @Relationship(deleteRule: .nullify, inverse: \AnnotationData.to) var from: AnnotationData? var to: AnnotationData? var history: History? } // MARK: - History @Model class History { var id: UUID = UUID() var timestamp: Date = Date() @Relationship(deleteRule: .nullify, inverse: \AnnotationData.history) var annotations: [AnnotationData]? @Relationship(deleteRule: .nullify, inverse: \GroupData.history) var groups: [GroupData]? @Relationship(deleteRule: .nullify, inverse: \Item.history) var items: [Item]? @Relationship(deleteRule: .nullify, inverse: \Deployment.history) var deployment: Deployment? var formattedDate: String { let formatter = DateFormatter() formatter.dateStyle = .medium formatter.timeStyle = .short return formatter.string(from: timestamp) } var timeAgo: String { let formatter = RelativeDateTimeFormatter() formatter.unitsStyle = .abbreviated return formatter.localizedString(for: timestamp, relativeTo: Date()) } } } So when trying to sync with the code in documentation let modelContainer: ModelContainer init() { let config = ModelConfiguration() typealias vs = LinkMapV3_1 do { #if DEBUG // Use an autorelease pool to make sure Swift deallocates the persistent // container before setting up the SwiftData stack. try autoreleasepool { let desc = NSPersistentStoreDescription(url: config.url) let opts = NSPersistentCloudKitContainerOptions(containerIdentifier: "iCloud.name.Endsunset.LinkMap.SwiftData.v1") desc.cloudKitContainerOptions = opts // Load the store synchronously so it completes before initializing the // CloudKit schema. desc.shouldAddStoreAsynchronously = false if let mom = NSManagedObjectModel.makeManagedObjectModel(for: [vs.AnnotationData.self, vs.GroupData.self, vs.Item.self, vs.Deployment.self, vs.History.self]) { let container = NSPersistentCloudKitContainer(name: "LinkMap", managedObjectModel: mom) container.persistentStoreDescriptions = [desc] container.loadPersistentStores {_, err in if let err { fatalError(err.localizedDescription) } } // Initialize the CloudKit schema after the store finishes loading. try container.initializeCloudKitSchema() // Remove and unload the store from the persistent container. if let store = container.persistentStoreCoordinator.persistentStores.first { try container.persistentStoreCoordinator.remove(store) } } } #endif modelContainer = try ModelContainer(for: vs.AnnotationData.self, vs.GroupData.self, vs.Item.self, vs.Deployment.self, vs.History.self, configurations: config) } catch { fatalError(error.localizedDescription) } } The output is Console Output Where you can see Output Extract Optional arrays with @Relationship are missing, and the entry of record types on cloudkit database container are also missing it. When I attempt to insert an annotation, I got SwiftData/PersistentModel.swift:559: Fatal error: This KeyPath does not appear to relate AnnotationData to anything - \AnnotationData.groups It gets more suspicious when restart the app and try again, the above error end with "AnnotationData.history", and if I tried again the above error end with "AnnotationData.from"... and so on. No matter how my app stop working.
1
0
348
Jan ’26
What is going on with transformable
Hi, I keep trying to use transformable to store an array of strings with SwiftData, and I can see that it is activating the transformer, but it keeps saying that I am still using NSArray instead of NSData. *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Unacceptable type of value for attribute: property = "category"; desired type = NSData; given type = Swift.__SwiftDeferredNSArray; value = ( yo, gurt ).' terminating due to uncaught exception of type NSException CoreSimulator 1010.10 - Device: iPhone 16 18.0 (6879535B-3174-4025-AD37-ED06E60291AD) - Runtime: iOS 18.0 (22A3351) - DeviceType: iPhone 16 Message from debugger: killed @Model class MyModel: Identifiable, Equatable { @Attribute(.transformable(by: StringArrayTransformer.self)) var category: [String]? @Attribute(.transformable(by: StringArrayTransformer.self)) var amenities: [String]? var image: String? var parentChunck: MyModelDataChunk_V1? init(category: [String]?, amenities: [String]?) { self.category = category self.amenities = amenities } } class StringArrayTransformer: ValueTransformer { override func transformedValue(_ value: Any?) -> Any? { print(value) guard let array = value as? [String] else { return nil } let data = try? JSONSerialization.data(withJSONObject: array, options: []) print(data) return data } override func reverseTransformedValue(_ value: Any?) -> Any? { guard let data = value as? Data else { return nil } let string = (try? JSONSerialization.jsonObject(with: data, options: [])) as? [String] print(string) return string } override class func transformedValueClass() -> AnyClass { return NSData.self } override class func allowsReverseTransformation() -> Bool { return true } static func register() { print("regitsering") ValueTransformer.setValueTransformer(StringArrayTransformer(), forName: .stringArrayTransformerName) } } extension NSValueTransformerName { static let stringArrayTransformerName = NSValueTransformerName("StringArrayTransformer") }
1
0
177
Jul ’25
How to figure out sync errors in Production?
I'm using SwiftData with CloudKit private database. I was able to identify the error on my device by debugging in Xcode with com.apple.CoreData.SQLDebug flag. However, in Production, I couldn't find a way to get the cause of errors. I tried inspecting the error coming from eventChangedNotification. The NSPersistentCloudKitContainer.Event error does not contain any underlying error (neither CKError.userInfo nor in NSError.underlyingError). It only reports a partial failure with CKErrorDomain code 2. If a user encounter an error, there seems to be no way to retrieve the error details. Is there any way to access the error details or logs in Production?
1
0
403
Jan ’26
CloudKit sync fails across TestFlight iOS + macOS builds — “Field recordName is not marked queryable”
I’m running into a CloudKit sync issue that I can’t reconcile after multiple rebuilds, TestFlight uploads, and entitlement verification, and I’m hoping for guidance on what I’m missing or whether this is expected behavior. Context App: RankSpinnah Platforms: iOS + macOS Distribution: TestFlight Xcode: 26.x Both apps use the same bundle identifier, same container, and same Apple Developer team Automatic signing enabled; Xcode-managed profiles CloudKit capability enabled for both targets Both builds install and run correctly from TestFlight on: iPhone 17 Pro Apple-silicon Mac (M5 MacBook Pro) The Problem CloudKit data does not sync at all between devices. On both iOS and macOS, CloudKit queries return no records, and I consistently see this error: Field 'recordName' is not marked queryable This occurs even when querying for records that should exist and after fresh installs on both devices. What I’ve Verified Same iCloud account signed in on both devices CloudKit container exists and is enabled App Sandbox enabled with network access CloudKit entitlements present in the signed app (verified from the archived .app) TestFlight builds are using the correct container Rebuilt and re-uploaded after version bump (1.2.0 / build 2026.02.03) Both iOS and macOS apps successfully uploaded and installed via TestFlight Despite this, no data syncs, and the queryable error persists. What I’m Unsure About Whether recordName is expected to be non-queryable in production schemas Whether TestFlight + CloudKit requires an explicit production schema deploy beyond what Xcode manages Whether this indicates a schema mismatch between development and production environments Or whether something subtle changed in recent Xcode / CloudKit behavior Ask Can someone clarify: Whether querying by recordName should work in production CloudKit What specifically causes the “Field recordName is not marked queryable” error in TestFlight builds What steps are required to ensure CloudKit schemas are correctly deployed for cross-platform sync At this point I feel like I’m missing one critical step, but I can’t identify what it is. Thanks in advance for any guidance.
1
0
187
Feb ’26
macOS 15.5 (Sequoia) – iCloud Drive Hydration/Sync Failures on M4 MBP
I’m seeing persistent issues with iCloud Drive hydration and Finder sync on a new M4 MacBook Pro running Sequoia 15.5 (24F74). The same folders hydrate correctly on other Macs (Intel and M1), but not on the M4. ✅ Tried: – killall bird – Safe Mode boot – Toggling iCloud Drive and System Settings > Apple ID – Isolating network, user profile, and running First Aid 🔍 Findings: – EtreCheck report shows consistent high CPU usage from bird with no resolution. – Console logs suggest bird is waiting on local metadata index. – No VPNs installed. No third-party sync tools active. I’ve sanitized and attached the EtreCheck report as text for reference (or can paste if needed). ❓ Questions: 1. Is this a known issue on M4 systems or Sequoia 15.5? 2. Could file system ownership have been impacted by command-line tools? 3. Is there a safe method to reset bird metadata or iCloud sync state locally? Any guidance from Apple or other developers would be appreciated. Thanks!
1
0
225
Jun ’25
swift
Hi, thank you for your reply. I have checked and confirmed that all AppleUser entity fields (id, name, email, password, createdAt) are optional, relationships (posts, comments) are optional, and I assign values when creating a new object, but Core Data still throws a nilError during registration; I have uploaded my project to GitHub for your reference here: https://github.com/Kawiichao/job. If reviewing it requires any payment, please let me know in advance. Thank you very much for your kind offer—I really appreciate it!
1
0
82
Sep ’25
CKShare in iOS 26
I have an app that uses CKShare to allow users to share CloudKit data with other users. With the first build of the iOS 26, I'm seeing a few issues: I'm not able to add myself as a participant anymore when I have the link to a document. Some participants names no longer show up in the app. Looking at the release notes for iOS & iPadOS 26 Beta, there is a CloudKit section with two bullets: CloudKit sharing URLs do not launch third-party apps. (151778655) The request access APIs, such as CKShareRequestAccessOperation, are available in the SDK but are currently nonfunctional. (151878020) It sounds like the first issue is addressed by the first bullet, although the error message makes me wonder if I need to make changes to my iCloud account permissions or something in order to open it. It works fine in iOS 18.5. This is the error I get when I try to open a link to a shared document (I blocked out my email address, which is what was in quotes): As far as the second issue, I am really confused about what is going on. Some names still show up, while others do not. I can't find a pattern, and the missing users are not on the iOS 26 beta. The release notes mention CKShareRequestAccessOperation being nonfunctional, which is new in the beta and has some minor documentation, but I can't find information about how it's supposed to be used yet. In previous years there have been WWDC sessions about what's new in CloudKit, but I haven't found anything that talks about these changes to document sharing. Is there a guide or session somewhere that I'm missing? Does anyone know what's going on with these changes to CloudKit?
13
0
419
Aug ’25
Widget error upon restore iPhone: The file "Name.sqlite" couldn't be opened
I have an app that uses NSPersistentCloudKitContainer stored in a shared location via App Groups so my widget can fetch data to display. It works. But if you reset your iPhone and restore it from a backup, an error occurs: The file "Name.sqlite" couldn't be opened. I suspect this happens because the widget is created before the app's data is restored. Restarting the iPhone is the only way to fix it though, opening the app and reloading timelines does not. Anything I can do to fix that to not require turning it off and on again?
12
0
340
Jul ’25
iOS 26 SwiftData crash does not happen in iOS 16
I have a simple app that makes an HTTPS call to gather some JSON which I then parse and add to my SwiftData database. The app then uses a simple @Query in a view to get the data into a list. on iOS 16 this works fine. No problems. But the same code on iOS 26 (targeting iOS 18.5) crashes after about 15 seconds of idle time after the list is populated. The error message is: Could not cast value of type '__NSCFNumber' (0x1f31ee568) to 'NSString' (0x1f31ec718). and occurs when trying to access ANY property of the list. I have a stripped down version of the app that shows the crash available. To replicate the issue: open the project in Xcode 26 target any iOS 26 device or simulator compile and run the project. after the list is displayed, wait about 15 seconds and the app crashes. It is also of note that if you try to run the app again, it will crash immediately, unless you delete the app from the device. Any help on this would be appreciated. Feedback number FB20295815 includes .zip file Below is the basic code (without the data models) The Best Seller List.Swift import SwiftUI import SwiftData @main struct Best_Seller_ListApp: App { var body: some Scene { WindowGroup { ContentView() } .modelContainer (for: NYTOverviewResponse.self) } } ContentView.Swift import os.log import SwiftUI struct ContentView: View { @Environment(\.modelContext) var modelContext @State private var listEncodedName = String() var body: some View { NavigationStack () { ListsView() } .task { await getBestSellerLists() } } func getBestSellerLists() async { guard let url = URL(string: "https://api.nytimes.com/svc/books/v3/lists/overview.json?api-key=\(NYT_API_KEY)") else { Logger.errorLog.error("Invalid URL") return } do { let decoder = JSONDecoder() var decodedResponse = NYTOverviewResponse() //decode the JSON let (data, _) = try await URLSession.shared.data(from: url) decoder.keyDecodingStrategy = .convertFromSnakeCase decodedResponse = try decoder.decode(NYTOverviewResponse.self, from: data) //remove any lists that don't have list_name_encoded. Fixes a bug in the data decodedResponse.results!.lists = decodedResponse.results!.lists!.filter { $0.listNameEncoded != "" } // sort the lists decodedResponse.results!.lists!.sort { (lhs, rhs) -> Bool in lhs.displayName < rhs.displayName } //delete any potential existing data try modelContext.delete(model: NYTOverviewResponse.self) //add the new data modelContext.insert(decodedResponse) } catch { Logger.errorLog.error("\(error.localizedDescription)") } } } ListsView.Swift import os.log import SwiftData import SwiftUI @MainActor struct ListsView: View { //MARK: - Variables and Constants @Query var nytOverviewResponses: [NYTOverviewResponse] enum Updated: String { case weekly = "WEEKLY" case monthly = "MONTHLY" } //MARK: - Main View var body: some View { List { if nytOverviewResponses.isEmpty { ContentUnavailableView("No lists yet", systemImage: "list.bullet", description: Text("NYT Bestseller lists not downloaded yet")) } else { WeeklySection MonthlySection } } .navigationBarTitle("Bestseller Lists", displayMode: .large) .listStyle(.grouped) } var WeeklySection: some View { let rawLists = nytOverviewResponses.last?.results?.lists ?? [] // Build a value-typed array to avoid SwiftData faulting during sort let weekly = rawLists .filter { $0.updateFrequency == Updated.weekly.rawValue } .map { (name: $0.displayName, encoded: $0.listNameEncoded, model: $0) } .sorted { $0.name < $1.name } return Section(header: Text("Weekly lists to be published on \(nytOverviewResponses.last?.results?.publishedDate ?? "-")")) { ForEach(weekly, id: \.encoded) { item in Text(item.name).font(Font.custom("Georgia", size: 17)) } } } var MonthlySection: some View { let rawLists = nytOverviewResponses.last?.results?.lists ?? [] // Build a value-typed array to avoid SwiftData faulting during sort let monthly = rawLists .filter { $0.updateFrequency == Updated.monthly.rawValue } .map { (name: $0.displayName, encoded: $0.listNameEncoded, model: $0) } .sorted { $0.name < $1.name } return Section(header: Text("Monthly lists to be published on \(nytOverviewResponses.last?.results?.publishedDate ?? "-")")) { ForEach(monthly, id: \.encoded) { item in Text(item.name).font(Font.custom("Georgia", size: 17)) } } } }
4
0
303
Sep ’25
Core Data + CKSyncEngine with Swift 6 — concurrency, Sendable, and best practices validation
Hi everyone, I’ve been working on migrating my app (SwimTimes, which helps swimmers track their times) to use Core Data + CKSyncEngine with Swift 6. After many iterations, forum searches, and experimentation, I’ve created a focused sample project that demonstrates the architecture I’m using. The good news: 👉 I believe the crashes I was experiencing are now solved, and the sync behavior is working correctly. 👉 The demo project compiles and runs cleanly with Swift 6. However, before adopting this as the final architecture, I’d like to ask the community (and hopefully Apple engineers) to validate a few critical points, especially regarding Swift 6 concurrency and Core Data contexts. Architecture Overview Persistence layer: Persistence.swift sets up the Core Data stack with a main viewContext and a background context for CKSyncEngine. Repositories: All Core Data access is abstracted into repository classes (UsersRepository, SwimTimesRepository), with async/await methods. SyncEngine: Wraps CKSyncEngine, handles system fields, sync tokens, and bridging between Core Data entities and CloudKit records. ViewModels: Marked @MainActor, exposing @Published arrays for SwiftUI. They never touch Core Data directly, only via repositories. UI: Simple SwiftUI views bound to the ViewModels. Entities: UserEntity → represents swimmers. SwimTimeEntity → times linked to a user (1-to-many). Current Status The project works and syncs across devices. But there are two open concerns I’d like validated: Concurrency & Memory Safety Am I correctly separating viewContext (main/UI) vs. background context (used by CKSyncEngine)? Could there still be hidden risks of race conditions or memory crashes that I’m not catching? Swift 6 Sendable Compliance Currently, I still need @unchecked Sendable in the SyncEngine and repository layers. What is the recommended way to fully remove these workarounds and make the code safe under Swift 6’s stricter concurrency rules? Request Please review this sample project and confirm whether the concurrency model is correct. Suggest how I can remove the @unchecked Sendable annotations safely. Any additional code improvements or best practices would also be very welcome — the intention is to share this as a community resource. I believe once finalized, this could serve as a good reference demo for Core Data + CKSyncEngine + Swift 6, helping others migrate safely. Environment iOS 18.5 Xcode 16.4 macOS 15.6 Swift 6 Sample Project Here is the full sample project on GitHub: 👉 [https://github.com/jarnaez728/coredata-cksyncengine-swift6] Thanks a lot for your time and for any insights! Best regards, Javier Arnáez de Pedro
3
0
485
Sep ’25
SwiftData crash when enabling CloudKit for existing users (Free to Pro upgrade)
Hi, I am implementing a premium feature in my app where CloudKit syncing is available only for "Pro" users. The Workflow: Free Users: I initialize the ModelContainer with cloudKitDatabase: .none so their data stays local. Pro Upgrade: When a user purchases a subscription, I restart the container with cloudKitDatabase: .automatic to enable syncing. The Problem: If a user starts as "Free" (creates local data) and later upgrades to "Pro", the app crashes immediately upon launch with the following error: Fatal error: Failed to create ModelContainer: SwiftDataError(_error: SwiftData.SwiftDataError._Error.loadIssueModelContainer, _explanation: nil) It seems that SwiftData fails to load the existing data once the configuration changes to expect a CloudKit-backed store. My Question: Is there a supported way to "toggle" CloudKit on for an existing local dataset without causing this crash? I want the user's existing local data to start syncing once they pay, but currently, it just crashes. My code: import Foundation import SwiftData public enum DataModelEnum: String { case task, calendar public static let container: ModelContainer = { let isSyncEnabled = UserDefaults.isProUser let config = ModelConfiguration( groupContainer: .identifier("group.com.yourcompany.myApp"), cloudKitDatabase: isSyncEnabled ? .automatic : .none ) do { return try ModelContainer(for: TaskModel.self, CalendarModel.self, configurations: config) } catch { fatalError("Failed to create ModelContainer: \(error)") } }() }
1
0
278
Dec ’25
How to handle required @relationship optionals in SwiftData CloudKit?
Hi all, As you know, when using SwiftData Cloudkit, all relationships are required to be optional. In my app, which is a list app, I have a model class Project that contains an array of Subproject model objects. A Subproject also contains an array of another type of model class and this chain goes on and on. In this type of pattern, it becomes really taxxing to handle the optionals the correct way, i.e. unwrap them as late as possible and display an error to the user if unable to. It seems like most developers don't even bother, they just wrap the array in a computed property that returns an empty array if nil. I'm just wondering what is the recommended way by Apple to handle these optionals. I'm not really familiar with how the CloudKit backend works, but if you have a simple list app that only saves to the users private iCloud, can I just handwave the optionals like so many do? Is it only big data apps that need to worry? Or should we always strive to handle them the correct way? If that's the case, why does it seem like most people skip over them? Be great if an Apple engineer could weigh in.
3
0
218
Oct ’25
What is going on with transformable
Hi, I keep trying to use transformable to store an array of strings with SwiftData, and I can see that it is activating the transformer, but it keeps saying that I am still using NSArray instead of NSData. *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Unacceptable type of value for attribute: property = "category"; desired type = NSData; given type = Swift.__SwiftDeferredNSArray; value = ( yo, gurt ).' terminating due to uncaught exception of type NSException CoreSimulator 1010.10 - Device: iPhone 16 18.0 (6879535B-3174-4025-AD37-ED06E60291AD) - Runtime: iOS 18.0 (22A3351) - DeviceType: iPhone 16 Message from debugger: killed @Model class MyModel: Identifiable, Equatable { @Attribute(.transformable(by: StringArrayTransformer.self)) var category: [String]? @Attribute(.transformable(by: StringArrayTransformer.self)) var amenities: [String]? var image: String? var parentChunck: HenricoPostDataChunk_V1? init(category: [String]?, amenities: [String]?) { self.category = category self.amenities = amenities } } class StringArrayTransformer: ValueTransformer { override func transformedValue(_ value: Any?) -> Any? { print(value) guard let array = value as? [String] else { return nil } let data = try? JSONSerialization.data(withJSONObject: array, options: []) print(data) return data } override func reverseTransformedValue(_ value: Any?) -> Any? { guard let data = value as? Data else { return nil } let string = (try? JSONSerialization.jsonObject(with: data, options: [])) as? [String] print(string) return string } override class func transformedValueClass() -> AnyClass { return NSData.self } override class func allowsReverseTransformation() -> Bool { return true } static func register() { print("regitsering") ValueTransformer.setValueTransformer(StringArrayTransformer(), forName: .stringArrayTransformerName) } } extension NSValueTransformerName { static let stringArrayTransformerName = NSValueTransformerName("StringArrayTransformer") }
3
0
236
Jul ’25
Unable to create record in public cloudkit database for missing/not authenticated iCloud user
While testing record creation in public CloudKit database for authenticated user I am able to do so without any issues. But for devices missing iCloud account or authentication expired I am seeing the below error: ▿ <CKError 0x97a959200: "Permission Failure" (10/2007); server message = "CREATE operation not permitted"; op = 67331DE3AF3DD666; uuid = 1F3ACD4F-A799-4CD4-ADF0-EDE9E12F2DCB; container ID = "***"> _nsError : <CKError 0x97a959200: "Permission Failure" (10/2007); server message = "CREATE operation not permitted"; op = 67331DE3AF3DD666; uuid = 1F3ACD4F-A799-4CD4-ADF0-EDE9E12F2DCB; container ID = "***"> I am unable to add create/write permission to _world security role in dashboard. Is this something not supported by Cloudkit? Only authenticated iCloud users will be able to create and write data to public database as well?
2
0
216
Feb ’26
Custom NSMigrationPolicy methods not invoked when NSMappingModel is created in code
Hi, I’m running into an issue with Core Data migrations using a custom NSMappingModel created entirely in Swift (not using .xcmappingmodel files). Setup: • I’m performing a migration with a manually constructed NSMappingModel • One of the NSEntityMapping instances is configured as follows: • mappingType = .customEntityMappingType (or .transformEntityMappingType) • entityMigrationPolicyClassName is set to a valid subclass of NSEntityMigrationPolicy • The class implements the expected methods like: @objc func createDestinationInstances(…) throws { … } @objc func createCustomDestinationInstance(…) throws -> NSManagedObject { … } The policy class is instantiated (confirmed via logging in init()), but none of the migration methods are ever called. I have also tried adding valid NSPropertyMapping instances with real valueExpression bindings to force activation, but that didn’t make a difference. Constraints: • I cannot use .xcmappingmodel files in this context due to transformable attributes not compatible with the visual editor. • Therefore, I need the entire mapping model to be defined in Swift. Workaround: As a temporary workaround, I’m migrating the data manually using two persistent stores and NSManagedObjectContext, but I’d prefer to rely on NSMigrationManager as designed. Question: Is there a known limitation that prevents Core Data from invoking NSMigrationPolicy methods when using in-memory NSMappingModel instances? Or is there any specific setup required to trigger them when not loading from .xcmappingmodel? Thanks in advance.
3
0
158
Oct ’25
Apple Account authorization instead of app-specific-password
Apple's app-specific password support article says: "For supported third-party apps that access your iCloud Mail, Calendar, and Contacts, you can authorize the app using your Apple Account instead of using an app-specific password." I can't find any documentation about (1) what makes an app "supported," (2) how to apply or qualify, or (3) the technical mechanics — Sign in with Apple, OAuth scopes, MDM, etc. I'm building an iOS app (already approved for Gmail with the gmail.modify scope and CASA-assessed) that monitors a user's mailbox for scam emails with their explicit consent. I'd love to offer the same to iCloud Mail users without requiring the manual app-specific password flow, if there's a Sign in with Apple-style alternative available. Has anyone had success applying for this, or can an Apple engineer point to additional documentation? Thanks!
2
0
212
4w
Sharing all container content
I've understood that SwiftData is not abled to share the whole content of a cloudkit database. So I'm trying to rewrite everything. Does someone knows id Sharing is coming on SwiftData at WWDC 26? Anyway, can someone can point me an example a a configured coredata stack that share all its content with other icloud users (with sharing pane and accept invitation code). At this step, on the owner side, I see some data in the default zone of my private container but nothing is visible on the shared zone. Maybe I don't understand where and when I should check shared data in cloudkit console. Need Help also here. See below by configuration stack: // Core Data container public lazy var container: NSPersistentContainer = { switch delegate.usage() { case .preview : return previewContainer() case .local : return localContainer() case .cloudKit : return cloudKitContainer() } }() private func cloudKitContainer() -> NSPersistentContainer { let modelURL = delegate.modelURL() let modelName = modelURL.deletingPathExtension().lastPathComponent guard let model = NSManagedObjectModel(contentsOf: modelURL) else { fatalError("Could not load Core Data model from \(modelURL)") } let container = NSPersistentCloudKitContainer( name: modelName, managedObjectModel: model ) let groupIdentifier = AppManager.shared.groupIdentifier guard let appGroupURL = FileManager.default.containerURL ( forSecurityApplicationGroupIdentifier: groupIdentifier ) else { fatalError("App Group not found: \(groupIdentifier)") } // MARK: - Private Store Configuration let privateStoreURL = appGroupURL.appendingPathComponent("\(modelName).sqlite") let privateStoreDescription = NSPersistentStoreDescription(url: privateStoreURL) // Persistent history tracking (MANDATORY) privateStoreDescription.setOption(true as NSNumber, forKey: NSPersistentHistoryTrackingKey) privateStoreDescription.setOption(true as NSNumber, forKey: NSPersistentStoreRemoteChangeNotificationPostOptionKey) // CloudKit options for private database // Core Data automatically uses the default zone: com.apple.coredata.cloudkit.zone let privateCloudKitOptions = NSPersistentCloudKitContainerOptions(containerIdentifier: delegate.cloudKitIdentifier()) privateCloudKitOptions.databaseScope = .private privateStoreDescription.cloudKitContainerOptions = privateCloudKitOptions // MARK: - Shared Store Configuration guard let sharedStoreDescription = privateStoreDescription.copy() as? NSPersistentStoreDescription else { fatalError("Create shareDesc error") } // The shared store receives zones that others share with us via CloudKit's shared database sharedStoreDescription.url = appGroupURL.appendingPathComponent("\(modelName)-shared.sqlite") // Persistent history tracking (MANDATORY) sharedStoreDescription.setOption(true as NSNumber, forKey: NSPersistentHistoryTrackingKey) sharedStoreDescription.setOption(true as NSNumber, forKey: NSPersistentStoreRemoteChangeNotificationPostOptionKey) // CloudKit options for shared database // This syncs data from CloudKit shared zones when we accept share invitations let sharedCloudKitOptions = NSPersistentCloudKitContainerOptions(containerIdentifier: delegate.cloudKitIdentifier()) sharedCloudKitOptions.databaseScope = .shared sharedStoreDescription.cloudKitContainerOptions = sharedCloudKitOptions // Configure both stores // Private store: com.apple.coredata.cloudkit.zone in private database // Shared store: Receives shared zones we're invited to container.persistentStoreDescriptions = [privateStoreDescription, sharedStoreDescription] container.loadPersistentStores { storeDescription, error in if let error = error as NSError? { fatalError("DB init error:\(error.localizedDescription)") } else if let cloudKitContiainerOptions = storeDescription.cloudKitContainerOptions { switch cloudKitContiainerOptions.databaseScope { case .private: self._privatePersistentStore = container.persistentStoreCoordinator.persistentStore(for: privateStoreDescription.url!) case .shared: self._sharedPersistentStore = container.persistentStoreCoordinator.persistentStore(for: sharedStoreDescription.url!) default: break } } let scope = storeDescription.cloudKitContainerOptions?.databaseScope == .shared ? "shared" : "private" print("✅ \(scope) store loaded at: \(storeDescription.url?.path ?? "unknown")") } // Auto-merge container.viewContext.automaticallyMergesChangesFromParent = true container.viewContext.mergePolicy = NSMergeByPropertyObjectTrumpMergePolicy do { try container.viewContext.setQueryGenerationFrom(.current) } catch { fatalError("Fail to pin viewContext to the current generation:\(error)") } return container }
7
0
391
Mar ’26
Using SwiftData with a local and CloudKit backed configuration at the same time
I'm trying to set up an application using SwiftData to have a number of models backed by a local datastore that's not synced to CloudKit, and another set of models that is. I was able to achieve this previously with Core Data using multiple NSPersistentStoreDescription instances. The set up code looks something like: do { let fullSchema = Schema([ UnsyncedModel.self, SyncedModel.self, ]) let localSchema = Schema([UnsyncedModel.self]) let localConfig = ModelConfiguration(schema: localSchema, cloudKitDatabase: .none) let remoteSchema = Schema([SyncedModel.self]) let remoteConfig = ModelConfiguration(schema: remoteSchema, cloudKitDatabase: .automatic) container = try ModelContainer(for: fullSchema, configurations: localConfig, remoteConfig) } catch { fatalError("Failed to configure SwiftData container.") } However, it doesn't seem to work as expected. If I remove the synced/remote schema and configuration then everything works fine, but the moment I add in the remote schema and configuration I get various different application crashes. Some examples below: A Core Data error occurred." UserInfo={Reason=Entity named:... not found for relationship named:..., Fatal error: Failed to identify a store that can hold instances of SwiftData._KKMDBackingData<...> Has anyone ever been able to get a similar setup to work using SwiftData?
3
0
437
Oct ’25
CloudKit it writes to development container, not Production
I have an app that I signed and distribute between some internal testflight users. Potentially I want to invite some 'Public' beta testers which don't need to validate (_World have read rights in the public database) Question: Do I need to have a working public CloudKit , when users are invited through TestFlight, or are they going to test on the development container? I understand that when I invite beta-tester without authorization (external testers) they cannot access the developer container, so therefore I need to have the production CloudKit container up and running. I have tried to populate the public production container, but for whatever reason my upload app still goes to the development container. I have archived the app, and tried, but no luck. I let xcode manage my certificates/profiles. but what do I need to change to be able to use my upload file to upload the production container, instead of the development. I tried: init() { container = CKContainer(identifier: "iCloud.com.xxxx.xxxx") publicDB = container.publicCloudDatabase I got no error in the console, but data is always populated to the development database, instead the production. I tried to create a provisioning profile, but for some reason Xcode doesn't like it. Tried to create one a different provisioning profile manual through the developer portal, for the app. but xcode doesn't want to use that, and mentions that the requirement are already in place. What can I check/do to solve this.
Replies
1
Boosts
0
Views
204
Activity
Aug ’25
Unable to sync SwiftData model fully using CloudKit
Hey everyone I just ran into an issue where I couldn't sync the model below fully by using CloudKit, enum LinkMapV3_1: VersionedSchema { static let versionIdentifier: Schema.Version = .init(3, 1, 0) static var models: [any PersistentModel.Type] { [AnnotationData.self, GroupData.self, Item.self, Deployment.self, History.self] } // MARK: - Data @Model class AnnotationData { var name: String = "" var longitude: Double = 0.0 var latitude: Double = 0.0 var order: Int = -1 var level: Int = 1 var detail: String = "" @Relationship(deleteRule: .nullify, inverse: \GroupData.annotation) var groups: [GroupData]? @Relationship(deleteRule: .nullify, inverse: \AnnotationData.to) var from: AnnotationData? var to: AnnotationData? var history: History? } // MARK: - History @Model class History { var id: UUID = UUID() var timestamp: Date = Date() @Relationship(deleteRule: .nullify, inverse: \AnnotationData.history) var annotations: [AnnotationData]? @Relationship(deleteRule: .nullify, inverse: \GroupData.history) var groups: [GroupData]? @Relationship(deleteRule: .nullify, inverse: \Item.history) var items: [Item]? @Relationship(deleteRule: .nullify, inverse: \Deployment.history) var deployment: Deployment? var formattedDate: String { let formatter = DateFormatter() formatter.dateStyle = .medium formatter.timeStyle = .short return formatter.string(from: timestamp) } var timeAgo: String { let formatter = RelativeDateTimeFormatter() formatter.unitsStyle = .abbreviated return formatter.localizedString(for: timestamp, relativeTo: Date()) } } } So when trying to sync with the code in documentation let modelContainer: ModelContainer init() { let config = ModelConfiguration() typealias vs = LinkMapV3_1 do { #if DEBUG // Use an autorelease pool to make sure Swift deallocates the persistent // container before setting up the SwiftData stack. try autoreleasepool { let desc = NSPersistentStoreDescription(url: config.url) let opts = NSPersistentCloudKitContainerOptions(containerIdentifier: "iCloud.name.Endsunset.LinkMap.SwiftData.v1") desc.cloudKitContainerOptions = opts // Load the store synchronously so it completes before initializing the // CloudKit schema. desc.shouldAddStoreAsynchronously = false if let mom = NSManagedObjectModel.makeManagedObjectModel(for: [vs.AnnotationData.self, vs.GroupData.self, vs.Item.self, vs.Deployment.self, vs.History.self]) { let container = NSPersistentCloudKitContainer(name: "LinkMap", managedObjectModel: mom) container.persistentStoreDescriptions = [desc] container.loadPersistentStores {_, err in if let err { fatalError(err.localizedDescription) } } // Initialize the CloudKit schema after the store finishes loading. try container.initializeCloudKitSchema() // Remove and unload the store from the persistent container. if let store = container.persistentStoreCoordinator.persistentStores.first { try container.persistentStoreCoordinator.remove(store) } } } #endif modelContainer = try ModelContainer(for: vs.AnnotationData.self, vs.GroupData.self, vs.Item.self, vs.Deployment.self, vs.History.self, configurations: config) } catch { fatalError(error.localizedDescription) } } The output is Console Output Where you can see Output Extract Optional arrays with @Relationship are missing, and the entry of record types on cloudkit database container are also missing it. When I attempt to insert an annotation, I got SwiftData/PersistentModel.swift:559: Fatal error: This KeyPath does not appear to relate AnnotationData to anything - \AnnotationData.groups It gets more suspicious when restart the app and try again, the above error end with "AnnotationData.history", and if I tried again the above error end with "AnnotationData.from"... and so on. No matter how my app stop working.
Replies
1
Boosts
0
Views
348
Activity
Jan ’26
What is going on with transformable
Hi, I keep trying to use transformable to store an array of strings with SwiftData, and I can see that it is activating the transformer, but it keeps saying that I am still using NSArray instead of NSData. *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Unacceptable type of value for attribute: property = "category"; desired type = NSData; given type = Swift.__SwiftDeferredNSArray; value = ( yo, gurt ).' terminating due to uncaught exception of type NSException CoreSimulator 1010.10 - Device: iPhone 16 18.0 (6879535B-3174-4025-AD37-ED06E60291AD) - Runtime: iOS 18.0 (22A3351) - DeviceType: iPhone 16 Message from debugger: killed @Model class MyModel: Identifiable, Equatable { @Attribute(.transformable(by: StringArrayTransformer.self)) var category: [String]? @Attribute(.transformable(by: StringArrayTransformer.self)) var amenities: [String]? var image: String? var parentChunck: MyModelDataChunk_V1? init(category: [String]?, amenities: [String]?) { self.category = category self.amenities = amenities } } class StringArrayTransformer: ValueTransformer { override func transformedValue(_ value: Any?) -> Any? { print(value) guard let array = value as? [String] else { return nil } let data = try? JSONSerialization.data(withJSONObject: array, options: []) print(data) return data } override func reverseTransformedValue(_ value: Any?) -> Any? { guard let data = value as? Data else { return nil } let string = (try? JSONSerialization.jsonObject(with: data, options: [])) as? [String] print(string) return string } override class func transformedValueClass() -> AnyClass { return NSData.self } override class func allowsReverseTransformation() -> Bool { return true } static func register() { print("regitsering") ValueTransformer.setValueTransformer(StringArrayTransformer(), forName: .stringArrayTransformerName) } } extension NSValueTransformerName { static let stringArrayTransformerName = NSValueTransformerName("StringArrayTransformer") }
Replies
1
Boosts
0
Views
177
Activity
Jul ’25
How to figure out sync errors in Production?
I'm using SwiftData with CloudKit private database. I was able to identify the error on my device by debugging in Xcode with com.apple.CoreData.SQLDebug flag. However, in Production, I couldn't find a way to get the cause of errors. I tried inspecting the error coming from eventChangedNotification. The NSPersistentCloudKitContainer.Event error does not contain any underlying error (neither CKError.userInfo nor in NSError.underlyingError). It only reports a partial failure with CKErrorDomain code 2. If a user encounter an error, there seems to be no way to retrieve the error details. Is there any way to access the error details or logs in Production?
Replies
1
Boosts
0
Views
403
Activity
Jan ’26
CloudKit sync fails across TestFlight iOS + macOS builds — “Field recordName is not marked queryable”
I’m running into a CloudKit sync issue that I can’t reconcile after multiple rebuilds, TestFlight uploads, and entitlement verification, and I’m hoping for guidance on what I’m missing or whether this is expected behavior. Context App: RankSpinnah Platforms: iOS + macOS Distribution: TestFlight Xcode: 26.x Both apps use the same bundle identifier, same container, and same Apple Developer team Automatic signing enabled; Xcode-managed profiles CloudKit capability enabled for both targets Both builds install and run correctly from TestFlight on: iPhone 17 Pro Apple-silicon Mac (M5 MacBook Pro) The Problem CloudKit data does not sync at all between devices. On both iOS and macOS, CloudKit queries return no records, and I consistently see this error: Field 'recordName' is not marked queryable This occurs even when querying for records that should exist and after fresh installs on both devices. What I’ve Verified Same iCloud account signed in on both devices CloudKit container exists and is enabled App Sandbox enabled with network access CloudKit entitlements present in the signed app (verified from the archived .app) TestFlight builds are using the correct container Rebuilt and re-uploaded after version bump (1.2.0 / build 2026.02.03) Both iOS and macOS apps successfully uploaded and installed via TestFlight Despite this, no data syncs, and the queryable error persists. What I’m Unsure About Whether recordName is expected to be non-queryable in production schemas Whether TestFlight + CloudKit requires an explicit production schema deploy beyond what Xcode manages Whether this indicates a schema mismatch between development and production environments Or whether something subtle changed in recent Xcode / CloudKit behavior Ask Can someone clarify: Whether querying by recordName should work in production CloudKit What specifically causes the “Field recordName is not marked queryable” error in TestFlight builds What steps are required to ensure CloudKit schemas are correctly deployed for cross-platform sync At this point I feel like I’m missing one critical step, but I can’t identify what it is. Thanks in advance for any guidance.
Replies
1
Boosts
0
Views
187
Activity
Feb ’26
macOS 15.5 (Sequoia) – iCloud Drive Hydration/Sync Failures on M4 MBP
I’m seeing persistent issues with iCloud Drive hydration and Finder sync on a new M4 MacBook Pro running Sequoia 15.5 (24F74). The same folders hydrate correctly on other Macs (Intel and M1), but not on the M4. ✅ Tried: – killall bird – Safe Mode boot – Toggling iCloud Drive and System Settings > Apple ID – Isolating network, user profile, and running First Aid 🔍 Findings: – EtreCheck report shows consistent high CPU usage from bird with no resolution. – Console logs suggest bird is waiting on local metadata index. – No VPNs installed. No third-party sync tools active. I’ve sanitized and attached the EtreCheck report as text for reference (or can paste if needed). ❓ Questions: 1. Is this a known issue on M4 systems or Sequoia 15.5? 2. Could file system ownership have been impacted by command-line tools? 3. Is there a safe method to reset bird metadata or iCloud sync state locally? Any guidance from Apple or other developers would be appreciated. Thanks!
Replies
1
Boosts
0
Views
225
Activity
Jun ’25
swift
Hi, thank you for your reply. I have checked and confirmed that all AppleUser entity fields (id, name, email, password, createdAt) are optional, relationships (posts, comments) are optional, and I assign values when creating a new object, but Core Data still throws a nilError during registration; I have uploaded my project to GitHub for your reference here: https://github.com/Kawiichao/job. If reviewing it requires any payment, please let me know in advance. Thank you very much for your kind offer—I really appreciate it!
Replies
1
Boosts
0
Views
82
Activity
Sep ’25
CKShare in iOS 26
I have an app that uses CKShare to allow users to share CloudKit data with other users. With the first build of the iOS 26, I'm seeing a few issues: I'm not able to add myself as a participant anymore when I have the link to a document. Some participants names no longer show up in the app. Looking at the release notes for iOS & iPadOS 26 Beta, there is a CloudKit section with two bullets: CloudKit sharing URLs do not launch third-party apps. (151778655) The request access APIs, such as CKShareRequestAccessOperation, are available in the SDK but are currently nonfunctional. (151878020) It sounds like the first issue is addressed by the first bullet, although the error message makes me wonder if I need to make changes to my iCloud account permissions or something in order to open it. It works fine in iOS 18.5. This is the error I get when I try to open a link to a shared document (I blocked out my email address, which is what was in quotes): As far as the second issue, I am really confused about what is going on. Some names still show up, while others do not. I can't find a pattern, and the missing users are not on the iOS 26 beta. The release notes mention CKShareRequestAccessOperation being nonfunctional, which is new in the beta and has some minor documentation, but I can't find information about how it's supposed to be used yet. In previous years there have been WWDC sessions about what's new in CloudKit, but I haven't found anything that talks about these changes to document sharing. Is there a guide or session somewhere that I'm missing? Does anyone know what's going on with these changes to CloudKit?
Replies
13
Boosts
0
Views
419
Activity
Aug ’25
Widget error upon restore iPhone: The file "Name.sqlite" couldn't be opened
I have an app that uses NSPersistentCloudKitContainer stored in a shared location via App Groups so my widget can fetch data to display. It works. But if you reset your iPhone and restore it from a backup, an error occurs: The file "Name.sqlite" couldn't be opened. I suspect this happens because the widget is created before the app's data is restored. Restarting the iPhone is the only way to fix it though, opening the app and reloading timelines does not. Anything I can do to fix that to not require turning it off and on again?
Replies
12
Boosts
0
Views
340
Activity
Jul ’25
iOS 26 SwiftData crash does not happen in iOS 16
I have a simple app that makes an HTTPS call to gather some JSON which I then parse and add to my SwiftData database. The app then uses a simple @Query in a view to get the data into a list. on iOS 16 this works fine. No problems. But the same code on iOS 26 (targeting iOS 18.5) crashes after about 15 seconds of idle time after the list is populated. The error message is: Could not cast value of type '__NSCFNumber' (0x1f31ee568) to 'NSString' (0x1f31ec718). and occurs when trying to access ANY property of the list. I have a stripped down version of the app that shows the crash available. To replicate the issue: open the project in Xcode 26 target any iOS 26 device or simulator compile and run the project. after the list is displayed, wait about 15 seconds and the app crashes. It is also of note that if you try to run the app again, it will crash immediately, unless you delete the app from the device. Any help on this would be appreciated. Feedback number FB20295815 includes .zip file Below is the basic code (without the data models) The Best Seller List.Swift import SwiftUI import SwiftData @main struct Best_Seller_ListApp: App { var body: some Scene { WindowGroup { ContentView() } .modelContainer (for: NYTOverviewResponse.self) } } ContentView.Swift import os.log import SwiftUI struct ContentView: View { @Environment(\.modelContext) var modelContext @State private var listEncodedName = String() var body: some View { NavigationStack () { ListsView() } .task { await getBestSellerLists() } } func getBestSellerLists() async { guard let url = URL(string: "https://api.nytimes.com/svc/books/v3/lists/overview.json?api-key=\(NYT_API_KEY)") else { Logger.errorLog.error("Invalid URL") return } do { let decoder = JSONDecoder() var decodedResponse = NYTOverviewResponse() //decode the JSON let (data, _) = try await URLSession.shared.data(from: url) decoder.keyDecodingStrategy = .convertFromSnakeCase decodedResponse = try decoder.decode(NYTOverviewResponse.self, from: data) //remove any lists that don't have list_name_encoded. Fixes a bug in the data decodedResponse.results!.lists = decodedResponse.results!.lists!.filter { $0.listNameEncoded != "" } // sort the lists decodedResponse.results!.lists!.sort { (lhs, rhs) -> Bool in lhs.displayName < rhs.displayName } //delete any potential existing data try modelContext.delete(model: NYTOverviewResponse.self) //add the new data modelContext.insert(decodedResponse) } catch { Logger.errorLog.error("\(error.localizedDescription)") } } } ListsView.Swift import os.log import SwiftData import SwiftUI @MainActor struct ListsView: View { //MARK: - Variables and Constants @Query var nytOverviewResponses: [NYTOverviewResponse] enum Updated: String { case weekly = "WEEKLY" case monthly = "MONTHLY" } //MARK: - Main View var body: some View { List { if nytOverviewResponses.isEmpty { ContentUnavailableView("No lists yet", systemImage: "list.bullet", description: Text("NYT Bestseller lists not downloaded yet")) } else { WeeklySection MonthlySection } } .navigationBarTitle("Bestseller Lists", displayMode: .large) .listStyle(.grouped) } var WeeklySection: some View { let rawLists = nytOverviewResponses.last?.results?.lists ?? [] // Build a value-typed array to avoid SwiftData faulting during sort let weekly = rawLists .filter { $0.updateFrequency == Updated.weekly.rawValue } .map { (name: $0.displayName, encoded: $0.listNameEncoded, model: $0) } .sorted { $0.name < $1.name } return Section(header: Text("Weekly lists to be published on \(nytOverviewResponses.last?.results?.publishedDate ?? "-")")) { ForEach(weekly, id: \.encoded) { item in Text(item.name).font(Font.custom("Georgia", size: 17)) } } } var MonthlySection: some View { let rawLists = nytOverviewResponses.last?.results?.lists ?? [] // Build a value-typed array to avoid SwiftData faulting during sort let monthly = rawLists .filter { $0.updateFrequency == Updated.monthly.rawValue } .map { (name: $0.displayName, encoded: $0.listNameEncoded, model: $0) } .sorted { $0.name < $1.name } return Section(header: Text("Monthly lists to be published on \(nytOverviewResponses.last?.results?.publishedDate ?? "-")")) { ForEach(monthly, id: \.encoded) { item in Text(item.name).font(Font.custom("Georgia", size: 17)) } } } }
Replies
4
Boosts
0
Views
303
Activity
Sep ’25
Core Data + CKSyncEngine with Swift 6 — concurrency, Sendable, and best practices validation
Hi everyone, I’ve been working on migrating my app (SwimTimes, which helps swimmers track their times) to use Core Data + CKSyncEngine with Swift 6. After many iterations, forum searches, and experimentation, I’ve created a focused sample project that demonstrates the architecture I’m using. The good news: 👉 I believe the crashes I was experiencing are now solved, and the sync behavior is working correctly. 👉 The demo project compiles and runs cleanly with Swift 6. However, before adopting this as the final architecture, I’d like to ask the community (and hopefully Apple engineers) to validate a few critical points, especially regarding Swift 6 concurrency and Core Data contexts. Architecture Overview Persistence layer: Persistence.swift sets up the Core Data stack with a main viewContext and a background context for CKSyncEngine. Repositories: All Core Data access is abstracted into repository classes (UsersRepository, SwimTimesRepository), with async/await methods. SyncEngine: Wraps CKSyncEngine, handles system fields, sync tokens, and bridging between Core Data entities and CloudKit records. ViewModels: Marked @MainActor, exposing @Published arrays for SwiftUI. They never touch Core Data directly, only via repositories. UI: Simple SwiftUI views bound to the ViewModels. Entities: UserEntity → represents swimmers. SwimTimeEntity → times linked to a user (1-to-many). Current Status The project works and syncs across devices. But there are two open concerns I’d like validated: Concurrency & Memory Safety Am I correctly separating viewContext (main/UI) vs. background context (used by CKSyncEngine)? Could there still be hidden risks of race conditions or memory crashes that I’m not catching? Swift 6 Sendable Compliance Currently, I still need @unchecked Sendable in the SyncEngine and repository layers. What is the recommended way to fully remove these workarounds and make the code safe under Swift 6’s stricter concurrency rules? Request Please review this sample project and confirm whether the concurrency model is correct. Suggest how I can remove the @unchecked Sendable annotations safely. Any additional code improvements or best practices would also be very welcome — the intention is to share this as a community resource. I believe once finalized, this could serve as a good reference demo for Core Data + CKSyncEngine + Swift 6, helping others migrate safely. Environment iOS 18.5 Xcode 16.4 macOS 15.6 Swift 6 Sample Project Here is the full sample project on GitHub: 👉 [https://github.com/jarnaez728/coredata-cksyncengine-swift6] Thanks a lot for your time and for any insights! Best regards, Javier Arnáez de Pedro
Replies
3
Boosts
0
Views
485
Activity
Sep ’25
SwiftData crash when enabling CloudKit for existing users (Free to Pro upgrade)
Hi, I am implementing a premium feature in my app where CloudKit syncing is available only for "Pro" users. The Workflow: Free Users: I initialize the ModelContainer with cloudKitDatabase: .none so their data stays local. Pro Upgrade: When a user purchases a subscription, I restart the container with cloudKitDatabase: .automatic to enable syncing. The Problem: If a user starts as "Free" (creates local data) and later upgrades to "Pro", the app crashes immediately upon launch with the following error: Fatal error: Failed to create ModelContainer: SwiftDataError(_error: SwiftData.SwiftDataError._Error.loadIssueModelContainer, _explanation: nil) It seems that SwiftData fails to load the existing data once the configuration changes to expect a CloudKit-backed store. My Question: Is there a supported way to "toggle" CloudKit on for an existing local dataset without causing this crash? I want the user's existing local data to start syncing once they pay, but currently, it just crashes. My code: import Foundation import SwiftData public enum DataModelEnum: String { case task, calendar public static let container: ModelContainer = { let isSyncEnabled = UserDefaults.isProUser let config = ModelConfiguration( groupContainer: .identifier("group.com.yourcompany.myApp"), cloudKitDatabase: isSyncEnabled ? .automatic : .none ) do { return try ModelContainer(for: TaskModel.self, CalendarModel.self, configurations: config) } catch { fatalError("Failed to create ModelContainer: \(error)") } }() }
Replies
1
Boosts
0
Views
278
Activity
Dec ’25
How to handle required @relationship optionals in SwiftData CloudKit?
Hi all, As you know, when using SwiftData Cloudkit, all relationships are required to be optional. In my app, which is a list app, I have a model class Project that contains an array of Subproject model objects. A Subproject also contains an array of another type of model class and this chain goes on and on. In this type of pattern, it becomes really taxxing to handle the optionals the correct way, i.e. unwrap them as late as possible and display an error to the user if unable to. It seems like most developers don't even bother, they just wrap the array in a computed property that returns an empty array if nil. I'm just wondering what is the recommended way by Apple to handle these optionals. I'm not really familiar with how the CloudKit backend works, but if you have a simple list app that only saves to the users private iCloud, can I just handwave the optionals like so many do? Is it only big data apps that need to worry? Or should we always strive to handle them the correct way? If that's the case, why does it seem like most people skip over them? Be great if an Apple engineer could weigh in.
Replies
3
Boosts
0
Views
218
Activity
Oct ’25
What is going on with transformable
Hi, I keep trying to use transformable to store an array of strings with SwiftData, and I can see that it is activating the transformer, but it keeps saying that I am still using NSArray instead of NSData. *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Unacceptable type of value for attribute: property = "category"; desired type = NSData; given type = Swift.__SwiftDeferredNSArray; value = ( yo, gurt ).' terminating due to uncaught exception of type NSException CoreSimulator 1010.10 - Device: iPhone 16 18.0 (6879535B-3174-4025-AD37-ED06E60291AD) - Runtime: iOS 18.0 (22A3351) - DeviceType: iPhone 16 Message from debugger: killed @Model class MyModel: Identifiable, Equatable { @Attribute(.transformable(by: StringArrayTransformer.self)) var category: [String]? @Attribute(.transformable(by: StringArrayTransformer.self)) var amenities: [String]? var image: String? var parentChunck: HenricoPostDataChunk_V1? init(category: [String]?, amenities: [String]?) { self.category = category self.amenities = amenities } } class StringArrayTransformer: ValueTransformer { override func transformedValue(_ value: Any?) -> Any? { print(value) guard let array = value as? [String] else { return nil } let data = try? JSONSerialization.data(withJSONObject: array, options: []) print(data) return data } override func reverseTransformedValue(_ value: Any?) -> Any? { guard let data = value as? Data else { return nil } let string = (try? JSONSerialization.jsonObject(with: data, options: [])) as? [String] print(string) return string } override class func transformedValueClass() -> AnyClass { return NSData.self } override class func allowsReverseTransformation() -> Bool { return true } static func register() { print("regitsering") ValueTransformer.setValueTransformer(StringArrayTransformer(), forName: .stringArrayTransformerName) } } extension NSValueTransformerName { static let stringArrayTransformerName = NSValueTransformerName("StringArrayTransformer") }
Replies
3
Boosts
0
Views
236
Activity
Jul ’25
Unable to create record in public cloudkit database for missing/not authenticated iCloud user
While testing record creation in public CloudKit database for authenticated user I am able to do so without any issues. But for devices missing iCloud account or authentication expired I am seeing the below error: ▿ <CKError 0x97a959200: "Permission Failure" (10/2007); server message = "CREATE operation not permitted"; op = 67331DE3AF3DD666; uuid = 1F3ACD4F-A799-4CD4-ADF0-EDE9E12F2DCB; container ID = "***"> _nsError : <CKError 0x97a959200: "Permission Failure" (10/2007); server message = "CREATE operation not permitted"; op = 67331DE3AF3DD666; uuid = 1F3ACD4F-A799-4CD4-ADF0-EDE9E12F2DCB; container ID = "***"> I am unable to add create/write permission to _world security role in dashboard. Is this something not supported by Cloudkit? Only authenticated iCloud users will be able to create and write data to public database as well?
Replies
2
Boosts
0
Views
216
Activity
Feb ’26
Custom NSMigrationPolicy methods not invoked when NSMappingModel is created in code
Hi, I’m running into an issue with Core Data migrations using a custom NSMappingModel created entirely in Swift (not using .xcmappingmodel files). Setup: • I’m performing a migration with a manually constructed NSMappingModel • One of the NSEntityMapping instances is configured as follows: • mappingType = .customEntityMappingType (or .transformEntityMappingType) • entityMigrationPolicyClassName is set to a valid subclass of NSEntityMigrationPolicy • The class implements the expected methods like: @objc func createDestinationInstances(…) throws { … } @objc func createCustomDestinationInstance(…) throws -> NSManagedObject { … } The policy class is instantiated (confirmed via logging in init()), but none of the migration methods are ever called. I have also tried adding valid NSPropertyMapping instances with real valueExpression bindings to force activation, but that didn’t make a difference. Constraints: • I cannot use .xcmappingmodel files in this context due to transformable attributes not compatible with the visual editor. • Therefore, I need the entire mapping model to be defined in Swift. Workaround: As a temporary workaround, I’m migrating the data manually using two persistent stores and NSManagedObjectContext, but I’d prefer to rely on NSMigrationManager as designed. Question: Is there a known limitation that prevents Core Data from invoking NSMigrationPolicy methods when using in-memory NSMappingModel instances? Or is there any specific setup required to trigger them when not loading from .xcmappingmodel? Thanks in advance.
Replies
3
Boosts
0
Views
158
Activity
Oct ’25
Apple Account authorization instead of app-specific-password
Apple's app-specific password support article says: "For supported third-party apps that access your iCloud Mail, Calendar, and Contacts, you can authorize the app using your Apple Account instead of using an app-specific password." I can't find any documentation about (1) what makes an app "supported," (2) how to apply or qualify, or (3) the technical mechanics — Sign in with Apple, OAuth scopes, MDM, etc. I'm building an iOS app (already approved for Gmail with the gmail.modify scope and CASA-assessed) that monitors a user's mailbox for scam emails with their explicit consent. I'd love to offer the same to iCloud Mail users without requiring the manual app-specific password flow, if there's a Sign in with Apple-style alternative available. Has anyone had success applying for this, or can an Apple engineer point to additional documentation? Thanks!
Replies
2
Boosts
0
Views
212
Activity
4w
Sharing all container content
I've understood that SwiftData is not abled to share the whole content of a cloudkit database. So I'm trying to rewrite everything. Does someone knows id Sharing is coming on SwiftData at WWDC 26? Anyway, can someone can point me an example a a configured coredata stack that share all its content with other icloud users (with sharing pane and accept invitation code). At this step, on the owner side, I see some data in the default zone of my private container but nothing is visible on the shared zone. Maybe I don't understand where and when I should check shared data in cloudkit console. Need Help also here. See below by configuration stack: // Core Data container public lazy var container: NSPersistentContainer = { switch delegate.usage() { case .preview : return previewContainer() case .local : return localContainer() case .cloudKit : return cloudKitContainer() } }() private func cloudKitContainer() -> NSPersistentContainer { let modelURL = delegate.modelURL() let modelName = modelURL.deletingPathExtension().lastPathComponent guard let model = NSManagedObjectModel(contentsOf: modelURL) else { fatalError("Could not load Core Data model from \(modelURL)") } let container = NSPersistentCloudKitContainer( name: modelName, managedObjectModel: model ) let groupIdentifier = AppManager.shared.groupIdentifier guard let appGroupURL = FileManager.default.containerURL ( forSecurityApplicationGroupIdentifier: groupIdentifier ) else { fatalError("App Group not found: \(groupIdentifier)") } // MARK: - Private Store Configuration let privateStoreURL = appGroupURL.appendingPathComponent("\(modelName).sqlite") let privateStoreDescription = NSPersistentStoreDescription(url: privateStoreURL) // Persistent history tracking (MANDATORY) privateStoreDescription.setOption(true as NSNumber, forKey: NSPersistentHistoryTrackingKey) privateStoreDescription.setOption(true as NSNumber, forKey: NSPersistentStoreRemoteChangeNotificationPostOptionKey) // CloudKit options for private database // Core Data automatically uses the default zone: com.apple.coredata.cloudkit.zone let privateCloudKitOptions = NSPersistentCloudKitContainerOptions(containerIdentifier: delegate.cloudKitIdentifier()) privateCloudKitOptions.databaseScope = .private privateStoreDescription.cloudKitContainerOptions = privateCloudKitOptions // MARK: - Shared Store Configuration guard let sharedStoreDescription = privateStoreDescription.copy() as? NSPersistentStoreDescription else { fatalError("Create shareDesc error") } // The shared store receives zones that others share with us via CloudKit's shared database sharedStoreDescription.url = appGroupURL.appendingPathComponent("\(modelName)-shared.sqlite") // Persistent history tracking (MANDATORY) sharedStoreDescription.setOption(true as NSNumber, forKey: NSPersistentHistoryTrackingKey) sharedStoreDescription.setOption(true as NSNumber, forKey: NSPersistentStoreRemoteChangeNotificationPostOptionKey) // CloudKit options for shared database // This syncs data from CloudKit shared zones when we accept share invitations let sharedCloudKitOptions = NSPersistentCloudKitContainerOptions(containerIdentifier: delegate.cloudKitIdentifier()) sharedCloudKitOptions.databaseScope = .shared sharedStoreDescription.cloudKitContainerOptions = sharedCloudKitOptions // Configure both stores // Private store: com.apple.coredata.cloudkit.zone in private database // Shared store: Receives shared zones we're invited to container.persistentStoreDescriptions = [privateStoreDescription, sharedStoreDescription] container.loadPersistentStores { storeDescription, error in if let error = error as NSError? { fatalError("DB init error:\(error.localizedDescription)") } else if let cloudKitContiainerOptions = storeDescription.cloudKitContainerOptions { switch cloudKitContiainerOptions.databaseScope { case .private: self._privatePersistentStore = container.persistentStoreCoordinator.persistentStore(for: privateStoreDescription.url!) case .shared: self._sharedPersistentStore = container.persistentStoreCoordinator.persistentStore(for: sharedStoreDescription.url!) default: break } } let scope = storeDescription.cloudKitContainerOptions?.databaseScope == .shared ? "shared" : "private" print("✅ \(scope) store loaded at: \(storeDescription.url?.path ?? "unknown")") } // Auto-merge container.viewContext.automaticallyMergesChangesFromParent = true container.viewContext.mergePolicy = NSMergeByPropertyObjectTrumpMergePolicy do { try container.viewContext.setQueryGenerationFrom(.current) } catch { fatalError("Fail to pin viewContext to the current generation:\(error)") } return container }
Replies
7
Boosts
0
Views
391
Activity
Mar ’26
Using SwiftData with a local and CloudKit backed configuration at the same time
I'm trying to set up an application using SwiftData to have a number of models backed by a local datastore that's not synced to CloudKit, and another set of models that is. I was able to achieve this previously with Core Data using multiple NSPersistentStoreDescription instances. The set up code looks something like: do { let fullSchema = Schema([ UnsyncedModel.self, SyncedModel.self, ]) let localSchema = Schema([UnsyncedModel.self]) let localConfig = ModelConfiguration(schema: localSchema, cloudKitDatabase: .none) let remoteSchema = Schema([SyncedModel.self]) let remoteConfig = ModelConfiguration(schema: remoteSchema, cloudKitDatabase: .automatic) container = try ModelContainer(for: fullSchema, configurations: localConfig, remoteConfig) } catch { fatalError("Failed to configure SwiftData container.") } However, it doesn't seem to work as expected. If I remove the synced/remote schema and configuration then everything works fine, but the moment I add in the remote schema and configuration I get various different application crashes. Some examples below: A Core Data error occurred." UserInfo={Reason=Entity named:... not found for relationship named:..., Fatal error: Failed to identify a store that can hold instances of SwiftData._KKMDBackingData<...> Has anyone ever been able to get a similar setup to work using SwiftData?
Replies
3
Boosts
0
Views
437
Activity
Oct ’25
Does the CloudKit participant limit include the owner?
Does the CloudKit participant limit of 100 include the owner?
Replies
1
Boosts
0
Views
141
Activity
Jun ’25