iCloud & Data

RSS for tag

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

CloudKit Documentation

Posts under iCloud & Data subtopic

Post

Replies

Boosts

Views

Activity

No persistent stores error in SwiftData
I am following Apple's instruction to sync SwiftData with CloudKit. While initiating the ModelContainer, right after removing the store from Core Data, the error occurs: FAULT: NSInternalInconsistencyException: This NSPersistentStoreCoordinator has no persistent stores (unknown). It cannot perform a save operation.; (user info absent) I've tried removing default.store and its related files/folders before creating the ModelContainer with FileManager but it does not resolve the issue. Isn't it supposed to create a new store when the ModelContainer is initialized? I don't understand why this error occurs. Error disappears when I comment out the #if DEBUG block. Code: import CoreData import SwiftData import SwiftUI struct InitView: View { @Binding var modelContainer: ModelContainer? @Binding var isReady: Bool @State private var loadingDots = "" @State private var timer: Timer? var body: some View { VStack(spacing: 16) { Text("Loading\(loadingDots)") .font(.title2) .foregroundColor(.gray) } .padding() .onAppear { startAnimation() registerTransformers() let config = ModelConfiguration() let newContainer: ModelContainer 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.my-container-identifier") desc.cloudKitContainerOptions = opts // Load the store synchronously so it completes before initializing the // CloudKit schema. desc.shouldAddStoreAsynchronously = false if let mom = NSManagedObjectModel.makeManagedObjectModel(for: [Page.self]) { let container = NSPersistentCloudKitContainer(name: "Pages", 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) } } // let fileManager = FileManager.default // let sqliteURL = config.url // let urls: [URL] = [ // sqliteURL, // sqliteURL.deletingLastPathComponent().appendingPathComponent("default.store-shm"), // sqliteURL.deletingLastPathComponent().appendingPathComponent("default.store-wal"), // sqliteURL.deletingLastPathComponent().appendingPathComponent(".default_SUPPORT"), // sqliteURL.deletingLastPathComponent().appendingPathComponent("default_ckAssets") // ] // for url in urls { // try? fileManager.removeItem(at: url) // } } #endif newContainer = try ModelContainer(for: Page.self, configurations: config) // ERROR!!! } catch { fatalError(error.localizedDescription) } modelContainer = newContainer isReady = true } .onDisappear { stopAnimation() } } private func startAnimation() { timer = Timer.scheduledTimer( withTimeInterval: 0.5, repeats: true ) { _ in updateLoadingDots() } } private func stopAnimation() { timer?.invalidate() timer = nil } private func updateLoadingDots() { if loadingDots.count > 2 { loadingDots = "" } else { loadingDots += "." } } } import CoreData import SwiftData import SwiftUI @main struct MyApp: App { @State private var modelContainer: ModelContainer? @State private var isReady: Bool = false var body: some Scene { WindowGroup { if isReady, let modelContainer = modelContainer { ContentView() .modelContainer(modelContainer) } else { InitView(modelContainer: $modelContainer, isReady: $isReady) } } } }
2
0
142
May ’25
iCloud sync issues using NSPersistentCloudKitContainer for Core Data + CloudKit sync.
I have tried to set up iCloud sync. Despite fully isolating and resetting my development environment, the app fails with: NSCocoaErrorDomain Code=134060 (PersistentStoreIncompatibleVersionHashError) What I’ve done: Created a brand new CloudKit container Created a new bundle ID and app target Renamed the Core Data model file itself Set a new model version Used a new .sqlite store path Created a new .entitlements file with the correct container ID Verified that the CloudKit dashboard shows no records Deleted and reinstalled the app on a real device Also tested with “Automatically manage signing” and without Despite this, the error persists. I am very inexperienced and am not sure what my next step is to even attempt to fix this. Any guidance is apprecitated.
1
0
160
Jun ’25
SwiftData + CloudKit causes watchOS app termination during WKExtendedRuntimeSession (FB17685611)
Hi all, I’m encountering a consistent issue with SwiftData on watchOS when using CloudKit sync. After enabling: let config = ModelConfiguration(schema: schema, cloudKitDatabase: .automatic) …the app terminates ~30–60 seconds into a WKExtendedRuntimeSession. This happens specifically when: Always-On Display is OFF The iPhone is disconnected or in Airplane Mode The app is running in a WKExtendedRuntimeSession (e.g., used for meditation tracking) The Xcode logs show a warning: Background Task ("CoreData: CloudKit Setup"), was created over 30 seconds ago. In applications running in the background, this creates a risk of termination. It appears CloudKit sync setup is being triggered automatically and flagged by the system as an unmanaged long-running task, leading to termination. Workaround: Switching to: let config = ModelConfiguration(schema: schema, cloudKitDatabase: .none) …prevents the issue entirely — no background task warning, no crash. Feedback ID submitted: FB17685611 Just wanted to check if others have seen this behavior or found alternative solutions. It seems like something Apple may need to address in SwiftData’s CloudKit handling on watchOS.
1
1
183
May ’25
CKSyncEngine on macOS: Automatic Fetch Extremely Slow Compared to iOS
Hi everyone, We’re currently using CKSyncEngine to sync all our locally persisted data across user devices (iOS and macOS) via iCloud. We’ve noticed something strange and reproducible: On iOS, when the CKSyncEngine is initialized with manual sync behavior, both manual calls to fetchChanges() and sendChanges() happen nearly instantly (usually within seconds). Automatic syncing is also very fast. On macOS, when the CKSyncEngine is initialized with manual sync behavior, fetchChanges() and sendChanges() are also fast and responsive. However, once CKSyncEngine is initialized with automatic syncing enabled on macOS: sendChanges() still appears to transmit changes immediately. But automatic fetching becomes significantly slower — often taking minutes to pick up changes from the cloud, even when new data is already available. Even manual calls to fetchChanges() behave as if they’re throttled or delayed, rather than performing an immediate fetch. Our questions: Is this delay in automatic (and post-automatic manual) fetch behavior on macOS expected, or possibly a bug? Are there specific macOS constraints that impact CKSyncEngine differently than on iOS? Once CKSyncEngine has been initialized in automatic mode, is fetchChanges() no longer treated as a truly manual trigger? Is there a recommended workaround to enable fast sync behavior on macOS — for example, by sticking to manual sync configuration and triggering sync using a CKSubscription-based mechanism when remote changes occur? Any guidance, clarification, or experiences from other developers (or Apple engineers) would be greatly appreciated — especially regarding maintaining parity between iOS and macOS sync performance. Thanks in advance!
1
1
116
3w
Key-value storage will not sync data past a certain size
I have an app which uses key-value storage and will not sync data past a certain size -- meaning that device "A" will send the data to the cloud but device "B" will never receive the updated data. Device "B" will receive the NSUbiquitousKeyValueStoreDidChangeExternallyNotification that the KVS changed but the data is empty. The data in in the KVS is comprised of 4 keys, each containing a value of NSData generated by NSKeyedArchiver. The NSData is comprised of property-list data types (e.g. numbers, strings, dates, etc.) I've verified that the KVS meets the limits of: A total of 1 MB per app, with a per-key limit of 1 MB A per-key value size limit of 1 MB, and a maximum of 1024 keys A maximum length for key strings is 64 bytes using UTF8 encoding Also, the app has never received an NSUbiquitousKeyValueStoreQuotaViolationChange notification. Of the 4 keys, 3 of them contain no more than 30 KB of data each. However, one of the keys can contain as much as 160 KB of data which will not sync to another device. Strangely, if I constrain the data to 100 KB it will work, however, that is not ideal as it is a fraction of the necessary data. I don't see any errors in the debug log either. Any suggestions on what to try next to get this working?
2
0
132
May ’25
Migrating a swiftData project to CloudKit to implement iCloudSync.
My project is using swiftData and I want to implement iCloud sync in it. Now, my data base doesnt have any optional attributes or relationships and CloudKit wants them to be optional. So, rather than editing all code with unwrapping code for the optionals, how can I provide a bridge that does so in the last stage of actually saving to the store? Sort of, capture it in a proxy object before writing and after reading from the store. Is there a neat way that can save a lot of debugging? I have code snippets from chat gpt and they are hard to debug. This is my first project in swiftUI. Thanks. Neerav
3
0
132
Jun ’25
Persistent CloudKit Server-to-Server INTERNAL_ERROR (500) Despite Correct Key Parsing & Request Formatting for /users/current
Hello Devs, I'm encountering a persistent INTERNAL_ERROR (HTTP 500) when making Server-to-Server API calls to CloudKit, specifically when trying to hit the /users/current endpoint, even after meticulously verifying all client-side components. I'm hoping someone might have insight into what could cause this. Context: Goal: Authenticate to CloudKit from a Vercel Serverless Function (Node.js) to perform operations like record queries. Problem Endpoint: POST https://api.apple-cloudkit.com/database/1/iCloud.com.dannybaseball.Danny-Baseball/production/public/users/current Key Generation Method: Using the CloudKit Dashboard's "Tokens & Keys" -> "New Server-to-Server Key" flow, where I generate the private key using openssl ecparam -name prime256v1 -genkey -noout -out mykey.pem, then extract the public key using openssl ec -in mykey.pem -pubout, and paste the public key material (between BEGIN/END markers) into the dashboard. The private key was then converted to PKCS#8 format using openssl pkcs8 -topk8 -nocrypt -in mykey.pem -out mykey_pkcs8.pem. Current Setup Being Tested (in a Vercel Node.js function): CLOUDKIT_CONTAINER: iCloud.com.dannybaseball.Danny-Baseball CLOUDKIT_KEY_ID: 9368dddf141ce9bc0da743b9f69bc3eda132b9bb3e62a4167e428d4f320b656e (This is the Key ID generated from the CloudKit Dashboard for the public key I provided). CLOUDKIT_P8_KEY (Environment Variable): Contains the base64 encoded string of the entire content of my PKCS#8 formatted private key file. Key Processing in Code: const p8Base64 = process.env.CLOUDKIT_P8_KEY; const privateKeyPEM = Buffer.from(p8Base64, 'base64').toString('utf8'); // This privateKeyPEM string starts with "-----BEGIN PRIVATE KEY-----" and ends with "-----END PRIVATE KEY-----" const privateKey = crypto.createPrivateKey({ key: privateKeyPEM, format: 'pem' }); // This line SUCCEEDS without DECODER errors in my Vercel function logs. Use code with caution. JavaScript Request Body for /users/current: "{}" Signing String (message = Date:BodyHash:Path): Date: Correct ISO8601 format (e.g., "2025-05-21T19:38:11.886Z") BodyHash: Correct SHA256 hash of "{}", then Base64 encoded (e.g., "RBNvo1WzZ4oRRq0W9+hknpT7T8If536DEMBg9hyq/4o=") Path: Exactly /database/1/iCloud.com.dannybaseball.Danny-Baseball/production/public/users/current Headers: X-Apple-CloudKit-Request-KeyID: Set to the correct Key ID. X-Apple-CloudKit-Request-ISO8601Date: Set to the date used in the signature. X-Apple-CloudKit-Request-SignatureV1: Set to the generated signature. X-Apple-CloudKit-Environment: "production" Content-Type: "application/json" Observed Behavior & Logs: The Node.js crypto.createPrivateKey call successfully parses the decoded PEM key in my Vercel function. The request is sent to CloudKit. CloudKit responds with HTTP 500 and the following JSON body (UUID varies per request): { "uuid": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", "serverErrorCode": "INTERNAL_ERROR" } Use code with caution. Json This happens consistently. Previously, with other key pairs or different P8 processing attempts, I was getting AUTHENTICATION_FAILED (401) or local DECODER errors. Now that the key parsing is successful on my end with this current key pair and setup, I'm hitting this INTERNAL_ERROR. Troubleshooting Done: Verified Key ID (9368dddf...) is correct and corresponds to the key generated via CloudKit Dashboard. Verified Container ID (iCloud.com.dannybaseball.Danny-Baseball) is correct. Successfully parsed the private key from the environment variable (after base64 decoding) within the Vercel function. Meticulously checked the signing string components (Date, BodyHash, Path) against Apple's documentation. Path format is /database/1////. Ensured all required headers are present with correct values. Local Node.js tests (bypassing Vercel but using the same key data and signing logic) also result in this INTERNAL_ERROR. Question: What could cause CloudKit to return an INTERNAL_ERROR (500) for a /users/current request when the client-side key parsing is successful and all request components (path, body hash for signature, date, headers) appear to conform exactly to the Server-to-Server Web Services Reference? Are there any known subtle issues with EC keys generated via openssl ecparam (and then converted to PKCS#8) that might lead to this, even if crypto.createPrivateKey parses them in Node.js? Could there be an issue with my specific Key ID or container that would manifest this way, requiring Apple intervention? Any insights or suggestions would be greatly appreciated. I can provide more detailed logs of the request components if needed. Thank you!
1
1
84
May ’25
Login issues on CloudKit Console
Hi everyone In the last 24 hours, I’ve been running into some issues with the CloudKit console. Most of the time, I‘ll get an error stating an error has caused this web page to stop working correctly. Reloading doesn’t fix the issue, nor does using different browsers: Today I’ve got another error, something along the lines of the Console not being able to fetch the teams I’m assigned to and an XHF error pop-up. Has anyone encountered the same issues? After trying multiple times, I’m able to reach my database but it’s a bit frustrating as it’s very unreliable this way. Thanks for your feedback! Dave
1
3
73
May ’25
iCloud Drive changes in iOS 18.4 and later break stated API
The NSMetadataUbiquitousItemDownloadingStatusKey indicates the status of a ubiquitous (iCloud Drive) file. A key value of NSMetadataUbiquitousItemDownloadingStatusDownloaded is defined as indicating there is a local version of this file available. The most current version will get downloaded as soon as possible . However this no longer occurs since iOS 18.4. A ubiquitous file may remain in the NSMetadataUbiquitousItemDownloadingStatusDownloaded state for an indefinite period. There is a workaround: call [NSFileManager startDownloadingUbiquitousItemAtURL: error:] however this shouldn't be necessary, and introduces delays over the previous behaviour. Has anyone else seen this behaviour? Is this a permanent change? FB17662379
0
0
86
May ’25
can't reach CloudKit dashboard
Hello there, I have a problem reaching the CloudKit dashboard. Every time I login, the login successes but then I get the error: An error has caused this web page to stop working correctly. This also happens when I click on the Button CloudKit dashboard. Then I can reload the page, but the same errors occurs again and again. Can someone help me with this problem? Thank you very much
3
4
142
May ’25
ModelContext.model(for:) returns deleted objects
I'm writing some tests to confirm the behavior of my app. White creating a model actor to delete objects I realized that ModelContext.model(for:) does return objects that are deleted. I was able to reproduces this with this minimal test case: @Model class Activity { init() {} } struct MyLibraryTests { let modelContainer = try! ModelContainer( for: Activity.self, configurations: ModelConfiguration( isStoredInMemoryOnly: true ) ) init() throws { let context = ModelContext(modelContainer) context.insert(Activity()) try context.save() } @Test func modelForIdAfterDelete() async throws { let context = ModelContext(modelContainer) let id = try context.fetch(FetchDescriptor<Activity>()).first!.id context.delete(context.model(for: id) as! Activity) try context.save() let result = context.model(for: id) as? Activity #expect(result == nil) // Expectation failed: (result → MyLibrary.Activity) == nil } @Test func fetchDescriptorAfterDelete() async throws { let context = ModelContext(modelContainer) let id = try context.fetch(FetchDescriptor<Activity>()).first!.id context.delete(context.model(for: id) as! Activity) try context.save() let result = try context.fetch( FetchDescriptor<Activity>(predicate: #Predicate { $0.id == id }) ).first #expect(result == nil) } } Here I create a new context, insert an model and save it. The test modelForIdAfterDelete does fail, as result still contains the deleted object. I also tried to check #expect(result!.isDeleted), but it is also false. With the second test I use a FetchDescriptor to retrieve the object by ID and it correctly returns nil. Shouldn't both methods use a consistent behavior?
2
0
108
May ’25
CoreData Data Sharing with AppGroup
I have the following lines of code to access data through CoreData. import Foundation import CoreData import CloudKit class CoreDataManager { static let instance = CoreDataManager() let container: NSPersistentCloudKitContainer let context: NSManagedObjectContext init() { container = NSPersistentCloudKitContainer(name: "ABC") container.loadPersistentStores(completionHandler: { (storeDescription, error) in if let error = error as NSError? { print(error.userInfo) } }) context = container.viewContext context.automaticallyMergesChangesFromParent = true context.mergePolicy = NSMergePolicy(merge: .mergeByPropertyObjectTrumpMergePolicyType) } func save() { do { try container.viewContext.save() print("Saved successfully") } catch { print("Error in saving data: \(error.localizedDescription)") } } } I have confirmed that I can share data between iPhone and iPad. Now, I need to use AppGroup as well. I have changed my code as follows. import Foundation import CoreData import CloudKit class CoreDataManager { static let shared = CoreDataManager() let container: NSPersistentContainer let context: NSManagedObjectContext init() { container = NSPersistentCloudKitContainer(name: "ABC") container.persistentStoreDescriptions = [NSPersistentStoreDescription(url: FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: "some group name")!.appendingPathComponent("CoreDataMama.sqlite"))] container.loadPersistentStores(completionHandler: { (description, error) in if let error = error as NSError? { print("Unresolved error \(error), \(error.userInfo)") } }) context = container.viewContext context.automaticallyMergesChangesFromParent = true context.mergePolicy = NSMergePolicy(merge: .mergeByPropertyObjectTrumpMergePolicyType) } func save() { do { try container.viewContext.save() print("Saved successfully") } catch { print("Error in saving data: \(error.localizedDescription)") } } } Other files being unaltered, my sample apps aren't sharing data. What am I doing wrong? Just FYI, I'm using actual devices. Thank you for your reading this topic.
1
0
87
May ’25
ForEach and RandomAccessCollection
I'm trying to build a custom FetchRequest that I can use outside a View. I've built the following ObservableFetchRequest class based on this article: https://augmentedcode.io/2023/04/03/nsfetchedresultscontroller-wrapper-for-swiftui-view-models @Observable @MainActor class ObservableFetchRequest&lt;Result: Storable&gt;: NSObject, @preconcurrency NSFetchedResultsControllerDelegate { private let controller: NSFetchedResultsController&lt;Result.E&gt; private var results: [Result] = [] init(context: NSManagedObjectContext = .default, predicate: NSPredicate? = Result.E.defaultPredicate(), sortDescriptors: [NSSortDescriptor] = Result.E.sortDescripors) { guard let request = Result.E.fetchRequest() as? NSFetchRequest&lt;Result.E&gt; else { fatalError("Failed to create fetch request for \(Result.self)") } request.predicate = predicate request.sortDescriptors = sortDescriptors controller = NSFetchedResultsController(fetchRequest: request, managedObjectContext: context, sectionNameKeyPath: nil, cacheName: nil) super.init() controller.delegate = self fetch() } private func fetch() { do { try controller.performFetch() refresh() } catch { fatalError("Failed to fetch results for \(Result.self)") } } private func refresh() { results = controller.fetchedObjects?.map { Result($0) } ?? [] } var predicate: NSPredicate? { get { controller.fetchRequest.predicate } set { controller.fetchRequest.predicate = newValue fetch() } } var sortDescriptors: [NSSortDescriptor] { get { controller.fetchRequest.sortDescriptors ?? [] } set { controller.fetchRequest.sortDescriptors = newValue.isEmpty ? nil : newValue fetch() } } internal func controllerDidChangeContent(_ controller: NSFetchedResultsController&lt;any NSFetchRequestResult&gt;) { refresh() } } Till this point, everything works fine. Then, I conformed my class to RandomAccessCollection, so I could use in a ForEach loop without having to access the results property. extension ObservableFetchRequest: @preconcurrency RandomAccessCollection, @preconcurrency MutableCollection { subscript(position: Index) -&gt; Result { get { results[position] } set { results[position] = newValue } } public var endIndex: Index { results.endIndex } public var indices: Indices { results.indices } public var startIndex: Index { results.startIndex } public func distance(from start: Index, to end: Index) -&gt; Int { results.distance(from: start, to: end) } public func index(_ i: Index, offsetBy distance: Int) -&gt; Index { results.index(i, offsetBy: distance) } public func index(_ i: Index, offsetBy distance: Int, limitedBy limit: Index) -&gt; Index? { results.index(i, offsetBy: distance, limitedBy: limit) } public func index(after i: Index) -&gt; Index { results.index(after: i) } public func index(before i: Index) -&gt; Index { results.index(before: i) } public typealias Element = Result public typealias Index = Int } The issue is, when I update the ObservableFetchRequest predicate while searching, it causes a Index out of range error in the Collection subscript because the ForEach loop (or a List loop) access a old version of the array when the item property is optional. List(request, selection: $selection) { item in VStack(alignment: .leading) { Text(item.content) if let information = item.information { // here's the issue, if I leave this out, everything works Text(information) .font(.callout) .foregroundStyle(.secondary) } } .tag(item.id) .contextMenu { if Item.self is Client.Type { Button("Editar") { openWindow(ClientView(client: item as! Client), id: item.id!) } } } } Is it some RandomAccessCollection issue or a SwiftUI bug?
0
0
100
May ’25
macOS SwiftData app never syncs with CloudKit
I'm using SwiftData with CloutKit with a very simple app. Data syncs between iOS, iPadOS, and visionOS, but not macOS. From what I can tell, macOS is never getting CK messages unless I'm running the app from Xcode. I can listen for the CK messages and show a line in a debug overlay. This works perfectly when I run from Xcode. I can see the notifications and see updates in my app. However, if I just launch the app outside of Xcode I will never see any changes or notifications. It is as if the Mac app never even tries to contact CloudKit. Schema has been deployed in the CloudKit console. The app is based on the multi-platform Xcode template. Again, only the macOS version has this issue. Is there some extra permission or setting I need to set up in order to use CloudKit on macOS? @State private var publisher = NotificationCenter.default.publisher(for: NSPersistentCloudKitContainer.eventChangedNotification).receive(on: DispatchQueue.main) .onReceive(publisher) { notification in // Listen for changes in CK events if let userInfo = notification.userInfo, let event = userInfo[NSPersistentCloudKitContainer.eventNotificationUserInfoKey] as? NSPersistentCloudKitContainer.Event { let message = "CloudKit Sync: \(event.type.rawValue) - \(event.succeeded ? "Success" : "Failed") - \(event.description)" // Store for UI display syncNotifications.append(message) if syncNotifications.count > 10 { syncNotifications.removeFirst() } } } .overlay(alignment: .topTrailing) { if !syncNotifications.isEmpty { VStack(alignment: .leading) { ForEach(syncNotifications, id: \.self) { notification in Text(notification) .padding(8) } } .frame(width: 800, height: 500) .cornerRadius(8) .background(Color.secondary.opacity(0.2)) .padding() .transition(.move(edge: .top)) } }
1
0
141
May ’25
Export/Import data with SwiftData
Hi ! Would anyone know (if possible) how to create backup files to export and then import from the data recorded by SwiftData? For those who wish, here is a more detailed explanation of my case: I am developing a small management software with customers and events represented by distinct classes. I would like to have an "Export" button to create a file with all the instances of these 2 classes and another "Import" button to replace all the old data with the new ones from a previously exported file. I looked for several solutions but I'm a little lost...
0
0
106
May ’25
SwiftData 100% crash when fetching history with codable (test included!)
SwiftData crashes 100% when fetching history of a model that contains an optional codable property that's updated: SwiftData/Schema.swift:389: Fatal error: Failed to materialize a keypath for someCodableID.someID from CrashModel. It is possible that this path traverses a type that does not work with append(), please file a bug report with a test. Would really appreciate some help or even a workaround. Code: import Foundation import SwiftData import Testing struct VaultsSwiftDataKnownIssuesTests { @Test func testCodableCrashInHistoryFetch() async throws { let container = try ModelContainer( for: CrashModel.self, configurations: .init( isStoredInMemoryOnly: true ) ) let context = ModelContext(container) try SimpleHistoryChecker.hasLocalHistoryChanges(context: context) // 1: insert a new value and save let model = CrashModel() model.someCodableID = SomeCodableID(someID: "testid1") context.insert(model) try context.save() // 2: check history it's fine. try SimpleHistoryChecker.hasLocalHistoryChanges(context: context) // 3: update the inserted value before then save model.someCodableID = SomeCodableID(someID: "testid2") try context.save() // The next check will always crash on fetchHistory with this error: /* SwiftData/Schema.swift:389: Fatal error: Failed to materialize a keypath for someCodableID.someID from CrashModel. It is possible that this path traverses a type that does not work with append(), please file a bug report with a test. */ try SimpleHistoryChecker.hasLocalHistoryChanges(context: context) } } @Model final class CrashModel { // optional codable crashes. var someCodableID: SomeCodableID? // these actually work: //var someCodableID: SomeCodableID //var someCodableID: [SomeCodableID] init() {} } public struct SomeCodableID: Codable { public let someID: String } final class SimpleHistoryChecker { static func hasLocalHistoryChanges(context: ModelContext) throws { let descriptor = HistoryDescriptor<DefaultHistoryTransaction>() let history = try context.fetchHistory(descriptor) guard let last = history.last else { return } print(last) } }
0
0
68
May ’25
NSMetadataQuery not searching subdirectories in external ubiquity container
Testing Environment: iOS 18.4.1 / macOS 15.4.1 I am working on an iOS project that aims to utilize the user's iCloud Drive documents directory to save a specific directory-based file structure. Essentially, the app would create a root directory where the user chooses in iCloud Drive, then it would populate user generated files in various levels of nested directories. I have been attempting to use NSMetadataQuery with various predicates and search scopes but haven't been able to get it to directly monitor changes to files or directories that are not in the root directory. Instead, it only monitors files or directories in the root directory, and any changes in a subdirectory are considered an update to the direct children of the root directory. Example iCloud Drive Documents (Not app's ubiquity container) User Created Root Directory (Being monitored) File A Directory A File B An insertion or deletion within Directory A would only return a notification with userInfo containing data for NSMetadataQueryUpdateChangedItemsKey relating to Directory A, and not the file or directory itself that was inserted or deleted. (Query results array also only contain the direct children.) I have tried all combinations of these search scopes and predicates with no luck: query.searchScopes = [ rootDirectoryURL, NSMetadataQueryUbiquitousDocumentsScope, NSMetadataQueryAccessibleUbiquitousExternalDocumentsScope, ] NSPredicate(value: true) NSPredicate(format: "%K LIKE '*.md'", NSMetadataItemFSNameKey) NSPredicate(format: "%K BEGINSWITH %@", NSMetadataItemPathKey, url.path(percentEncoded: false)) I do see these warnings in the console upon starting my query: [CRIT] UNREACHABLE: failed to get container URL for com.apple.CloudDocs [ERROR] couldn't fetch remote operation IDs: NSError: Cocoa 257 "The file couldn’t be opened because you don’t have permission to view it." "Error returned from daemon: Error Domain=com.apple.accounts Code=7 "(null)"" But I am not sure what to make of that, since it does act normally for finding updates in the root directory. Hopefully this isn't a limitation of the API, as the only alternative I could think of would be to have multiple queries running for each nested directory that I needed updates for.
0
0
100
May ’25