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

Using relationships in SortDescriptor crashing on release
If use a SortDescriptor for a model and sort by some attribute from a relationship, in DEBUG mode it all works fine and sorts. However, in release mode, it is an instant crash. SortDescriptor(.name, order: .reverse) ---- works SortDescriptor(.assignedUser?.name, order: .reverse) ---- works in debug but crash in release. What is the issue here, is it that SwiftData just incompetent to do this?
2
0
106
Aug ’25
Swiftdata cloudkit synchronization issues
Hi, I did cloudkit synchronization using swiftdata. However, synchronization does not occur automatically, and synchronization occurs intermittently only when the device is closed and opened. For confirmation, after changing the data in Device 1 (saving), when the data is fetched from Device 2, there is no change. I've heard that there's still an issue with swiftdata sync and Apple is currently troubleshooting it, is the phenomenon I'm experiencing in the current version normal?
2
1
555
Oct ’25
Data Protection and SwiftData Containers
SwiftData ModelContainer instances don't seem to have a value for setting the Data Protection class. Is the best way to set that by setting the Data Protection in the app capabilities? Is that the only way? I have a need for log data that would be "Complete unless open" and user data that would be "Complete", but how do I change one of the containers data protection class?
2
1
874
Jan ’25
Is a 3-way merge possible when resolving CloudKit conflicts?
I'm trying to handle the serverRecordChanged return code you get in CKError when you have a conflict and your using the savePolicy of ifServerRecordUnchanged. According to the CKError.Code.serverRecordChanged documentation, I should be receiving all three records that I need to do a 3-way merge. The problem is that the ancestorRecord (CKRecordChangedErrorAncestorRecordKey can also be used to look it up in the userInfo) doesn't actually contain a record. It only contains the record metadata. Is there something I need to be doing to get the full ancestorRecord in the CKError? If not is it possible to query iCloud for the ancestorRecord? Given that iCloud has the change history (as I understand it), then it is theoretically possible. I just don't know how to do it if it is possible. Are 3-way merges even possible? The design of the serverRecordChanged looks like that is the intent, but I can't see how to do it with the data that CloudKit is providing.
2
2
799
Oct ’25
SwiftData and iCloud
I'm a first time developer for Swift, (getting on a bit!) but after programming in VB back in the late 90s I wanted to write an app for iPhone. I think I might have gone about it the wrong way, but I've got an app that works great on my iPhone or works great on my iPad. It saves the data persistently on device, but, no matter how much I try, what I read and even resorting to AI (ChatGPT & Gemini) I still can't get it to save the data on iCloud to synchronise between the two and work across the devices. I think it must be something pretty fundamental I'm doing (or more likely not doing) that is causing the issue. I'm setting up my signing and capabilities as per the available instructions but I always get a fatal error. I think it might be something to do with making fields optional, but at this point I'm second guessing myself and feeling a complete failure. Any advice or pointers would be really gratefully appreciated. I like my app and would like eventually to get it on the App Store but at this point in time I feel it should be on the failed projects heap! I've even tried a new Xcode project for iOS and asking it to use SwiftData and CloudKit - the default project should work - right? But it absolutely doesn't for me. Please send help!!
2
0
179
Apr ’25
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
167
May ’25
SwiftData public sharing
I have an Apple app that uses SwiftData and icloud to sync the App's data across users' devices. Everything is working well. However, I am facing the following issue: SwiftData does not support public sharing of the object graph with other users via iCloud. How can I overcome this limitation without stopping using SwiftData? Thanks in advance!
2
7
679
Jun ’25
NSPersistentCloudKitContainer not saving 50% of the time
I'm using NSPersistentCloudKitContainer to save, edit, and delete items, but it only works half of the time. When I delete an item and terminate the app and repoen, sometimes the item is still there and sometimes it isn't. The operations are simple enough: moc.delete(thing) try? moc.save() Here is my DataController. I'm happy to provide more info as needed class DataController: ObservableObject { let container: NSPersistentCloudKitContainer @Published var moc: NSManagedObjectContext init() { container = NSPersistentCloudKitContainer(name: "AppName") container.loadPersistentStores { description, error in if let error = error { print("Core Data failed to load: \(error.localizedDescription)") } } #if DEBUG do { try container.initializeCloudKitSchema(options: []) } catch { print("Error initializing CloudKit schema: \(error.localizedDescription)") } #endif moc = container.viewContext } }
2
0
391
Jan ’25
SwiftData Migration: Keeps failing at the end of willMigrate
I've been trying to setup a successful migration, but it keeps failing with this error: NSCloudKitMirroringDelegate are not reusable and should have a lifecycle tied to a given instance of NSPersistentStore. I can't find any information about this online. I added breakpoints throughout the code in willMigrate, and it originally failed on this line: try? context.save() I removed that, and it still failed. After I reload the app, it doesn't run the migration again and the app loads successfully. I figured since it crashed, it would keep trying, but I guess not. Here's how my migration is setup. enum MigrationV1ToV2: SchemaMigrationPlan { static var schemas: [any VersionedSchema.Type] { [SchemaV1.self, SchemaV2.self] } static var stages: [MigrationStage] { [stage] } static let stage = MigrationStage.custom( fromVersion: SchemaV1.self, toVersion: SchemaV2.self, willMigrate: { context in // Get cycles let cycles = try? context.fetch(FetchDescriptor<SchemaV1.Cycle>()) if let cycles { for cycle in cycles { // Create new recurring objects based on what's in the cycle for income in cycle.income { let recurring = SchemaV2.Recurring(name: income.name, frequency: income.frequency, kind: .income) recurring.addAmount(.init(date: cycle.startDate, amount: income.amount)) context.insert(recurring) } for expense in cycle.expenses { let recurring = SchemaV2.Recurring(name: expense.name, frequency: expense.frequency, kind: .expense) recurring.addAmount(.init(date: cycle.startDate, amount: expense.amount)) context.insert(recurring) } for savings in cycle.savings { let recurring = SchemaV2.Recurring(name: savings.name, frequency: savings.frequency, kind: .savings) recurring.addAmount(.init(date: cycle.startDate, amount: savings.amount)) context.insert(recurring) } for investment in cycle.investments { let recurring = SchemaV2.Recurring(name: investment.name, frequency: investment.frequency, kind: .investment) recurring.addAmount(.init(date: cycle.startDate, amount: investment.amount)) context.insert(recurring) } } //try? context.save() } else { print("The cycles were not able to be fetched.") } }, didMigrate: { context in // Get new recurring objects let newRecurring = try? context.fetch(FetchDescriptor<SchemaV2.Recurring>()) if let newRecurring { for recurring in newRecurring { // Get all recurring with the same name and kind let sameName = newRecurring.filter({ $0.name == recurring.name && $0.kind == recurring.kind }) // Add amount history to recurring object, and then remove matching for match in sameName { recurring.amountHistory.append(contentsOf: match.amountHistory) context.delete(match) } } //try? context.save() } else { print("The new recurring objects could not be fetched.") } } ) } Here's is my modelContainer in the app file. There is a fatal error occurring here that's crashing the app. var sharedModelContainer: ModelContainer = { let schema = Schema(versionedSchema: SchemaV2.self) let modelConfiguration = ModelConfiguration(schema: schema, isStoredInMemoryOnly: false) do { return try ModelContainer( for: schema, migrationPlan: MigrationV1ToV2.self, configurations: [modelConfiguration] ) } catch { fatalError("Could not create ModelContainer: \(error)") } }() Does anyone have any suggestions for this? EDIT: I found this error in the console that may be relevant. BUG IN CLIENT OF CLOUDKIT: Registering a handler for a CKScheduler activity identifier that has already been registered (com.apple.coredata.cloudkit.activity.export.8F7A1261-4324-40B4-B041-886DF36FBF0A). CloudKit setup failed because it couldn't register a handler for the export activity. There is another instance of this persistent store actively syncing with CloudKit in this process. And here is the fatal error Fatal error: Could not create ModelContainer: SwiftDataError(_error: SwiftData.SwiftDataError._Error.loadIssueModelContainer, _explanation: nil)
2
3
625
Jan ’25
CKSyncEngine save existing CKRecord
I have transitioned to CKSyncEngine for syncing data to iCloud, and it is working quite well. I have a question regarding best practices for modifying and saving a CKRecord which already exists in the private or shared database. In my current app, most CKRecords will never be modified after saving to the database, so I do not persist a received record locally after updating my local data model. In the rare event that the local data for that record is modified, I manually fetch the associated server record from the database, modify it, and then use CKSyncEngine to save the modified record. As an alternative method, I can create a new CKRecord locally with the corresponding recordID and the modified data, and then use CKSyncEngine to attempt to save that record to the database. Doing so generates an error in the delegate method handleSentRecordZoneChanges, where I receive the local record I tried to save back inevent.failedRecordSaves with a .serverRecordChanged error, along with the corresponding server CKRecord. I can then update that server record with the local data and re-save using CKSyncEngine. I have not yet seen any issues when doing it this way. The advantage of the latter method is that CKSyncEngine handles the entire database operation, eliminating the manual fetch step. My question is: is this an acceptable practice, or could this result in other unforeseen issues?
2
0
98
Apr ’25
NSFetchedResultsController index out of bounds during context merging changes
I've noticed several crashes that look like they're caused by an index out of bound in internal methods of NSFetchedResultsController. This happens while changes are merged from the persistent store container into the view context. Here's an example of the last exception backtrace. Exactly which internal methods that are called in - [NSFetchedResultsController(PrivateMethods) _core_managedObjectContextDidChange:] vary between crash reports but they all end up crashing from _NSArrayRaiseBoundException. The Core Data stack consists of one persistent store, one persistent store coordinator that the view context is set up to automatically merge changes from, and data is saved to disk from background context. persistentContainer.loadPersistentStores(...) viewContext = persistentContainer.viewContext viewContext.automaticallyMergesChangesFromParent = true backgroundContext = persistentContainer.newBackgroundContext() backgroundContext.mergePolicy = NSMergeByPropertyObjectTrumpMergePolicy backgroundClientContext = persistentContainer.newBackgroundContext() backgroundClientContext.mergePolicy = NSMergeByPropertyObjectTrumpMergePolicy Does anyone have any ideas what could be causing this? Thankful for any ideas or advice on how to investigate further.
2
0
729
Jan ’25
How to import large data from Server and save it to Swift Data
Here’s the situation: • You’re downloading a huge list of data from iCloud. • You’re saving it one by one (sequentially) into SwiftData. • You don’t want the SwiftUI view to refresh until all the data is imported. • After all the import is finished, SwiftUI should show the new data. The Problem If you insert into the same ModelContext that SwiftUI’s @Environment(.modelContext) is watching, each insert may cause SwiftUI to start reloading immediately. That will make the UI feel slow, and glitchy, because SwiftUI will keep trying to re-render while you’re still importing. How to achieve this in Swift Data ?
2
0
126
Apr ’25
Safari App Extension fails to connect to CloudKit daemon (cloudd) with XPC communication errors -- CKErrorDomain Code=6 / NSCocoaErrorDomain Code=4099 – Unable to connect to CloudKit daemon
I'm working on a macOS app with a Safari web extension. I'm trying to share a SwiftData model between devices using CloudKit synchronization. I am able to get synchronization in the main app on the same device, CloudKit sync works correctly — changes appear in the CloudKit Dashboard under com.apple.coredata.cloudkit.zone. However, in the Safari App Extension, data is saved locally and persists across launches, but never syncs to CloudKit. I have followed the recommended practices for configuring the App Group and entitlements, but the issue persists. Questions: Is there an official limitation preventing Safari App Extensions from connecting to the CloudKit daemon (cloudd)? If not, what entitlements or configuration changes are required for a Safari App Extension to successfully sync with CloudKit? Is the xpc_error=159 from bootstrap_look_up() a known sandbox restriction for this extension type? Any guidance from Apple engineers or others who have successfully used CloudKit from a Safari App Extension would be appreciated. What I’ve confirmed: The extension’s .entitlements includes: com.apple.security.app-sandbox com.apple.developer.icloud-services CloudKit com.apple.developer.icloud-container-identifiers iCloud.dev.example.myapp Same iCloud container ID for both app and extension CloudKit container exists and is initialized in CloudKit Console Running in :Sandbox environment during development Database name in SwiftData matches container identifier (without the iCloud. prefix) The extension’s codesign output shows correct entitlements App Group is configured (although in this case, extension and app use separate stores intentionally) Observed behavior in Console.app logs: CloudKit sync engine initializes in the extension XPC activities are registered for import/export: _xpc_activity_register: com.apple.coredata.cloudkit.activity.export. xpc_activity_set_criteria: ... import. Then a bootstrap lookup fails: failed to do a bootstrap look-up: xpc_error=[159: Unknown error: 159] CloudKit daemon connection error: CKErrorDomain Code=6 "Error connecting to CloudKit daemon" NSCocoaErrorDomain Code=4099 There is no “Will attempt to upload transactions” or “Upload succeeded” logs are ever seen. Symptoms When the extension is run, I see logs like the following in Console.app: [0x13e215820] failed to do a bootstrap look-up: xpc_error=[159: Unknown error: 159] CoreData+CloudKit: -[PFCloudKitSetupAssistant _checkAccountStatus:]_block_invoke(342): Fetched account info for store : (null) Error Domain=CKErrorDomain Code=6 "Error connecting to CloudKit daemon. This could happen for many reasons..."
2
0
115
Aug ’25
NSPersistentCloudKitContainer - Import failed with error: Error Domain=NSCocoaErrorDomain Code=4864
The NSPersistentCloudKitContainer synchronization between core data and iCloud was working fine with phone 15.1. Connected a new iPhone iOS 15.5, it gives error: CoreData: debug: CoreData+CloudKit: -[NSCloudKitMirroringDelegate managedObjectContextSaved:](2504): <NSCloudKitMirroringDelegate: 0x28198c000>: Observed context save: <NSPersistentStoreCoordinator: 0x2809c9420> - <NSManagedObjectContext: 0x2819ad520> 2022-12-05 13:32:28.377000-0600 r2nr[340:6373] [error] error: CoreData+CloudKit: -[NSCloudKitMirroringDelegate _importFinishedWithResult:importer:](1245): <PFCloudKitImporter: 0x2837dd740>: Import failed with error: Error Domain=NSCocoaErrorDomain Code=4864 "*** -[NSKeyedUnarchiver _initForReadingFromData:error:throwLegacyExceptions:]: incomprehensible archive (0x53, 0x6f, 0x6d, 0x65, 0x20, 0x65, 0x78, 0x61)" UserInfo={NSDebugDescription=*** -[NSKeyedUnarchiver _initForReadingFromData:error:throwLegacyExceptions:]: incomprehensible archive (0x53, 0x6f, 0x6d, 0x65, 0x20, 0x65, 0x78, 0x61)} CoreData: error: CoreData+CloudKit: -[NSCloudKitMirroringDelegate _importFinishedWithResult:importer:](1245): <PFCloudKitImporter: 0x2837dd740>: Import failed with error: Error Domain=NSCocoaErrorDomain Code=4864 "*** -[NSKeyedUnarchiver _initForReadingFromData:error:throwLegacyExceptions:]: incomprehensible archive (0x53, 0x6f, 0x6d, 0x65, 0x20, 0x65, 0x78, 0x61)" UserInfo={NSDebugDescription=*** -[NSKeyedUnarchiver _initForReadingFromData:error:throwLegacyExceptions:]: incomprehensible archive (0x53, 0x6f, 0x6d, 0x65, 0x20, 0x65, 0x78, 0x61)} I go back and try with my old iPhone iOS 15.1, gives same error.
2
1
1.1k
Aug ’25
SwiftData JSONDataStore with relationships
I am trying to add a custom JSON DataStore and DataStoreConfiguration for SwiftData. Apple kindly provided some sample code in the WWDC24 session, "Create a custom data store with SwiftData", and (once updated for API changes since WWDC) that works fine. However, when I try to add a relationship between two classes, it fails. Has anyone successfully made a JSONDataStore with a relationship? Here's my code; firstly the cleaned up code from the WWDC session: import SwiftData final class JSONStoreConfiguration: DataStoreConfiguration { typealias Store = JSONStore var name: String var schema: Schema? var fileURL: URL init(name: String, schema: Schema? = nil, fileURL: URL) { self.name = name self.schema = schema self.fileURL = fileURL } static func == (lhs: JSONStoreConfiguration, rhs: JSONStoreConfiguration) -> Bool { return lhs.name == rhs.name } func hash(into hasher: inout Hasher) { hasher.combine(name) } } final class JSONStore: DataStore { typealias Configuration = JSONStoreConfiguration typealias Snapshot = DefaultSnapshot var configuration: JSONStoreConfiguration var name: String var schema: Schema var identifier: String init(_ configuration: JSONStoreConfiguration, migrationPlan: (any SchemaMigrationPlan.Type)?) throws { self.configuration = configuration self.name = configuration.name self.schema = configuration.schema! self.identifier = configuration.fileURL.lastPathComponent } func save(_ request: DataStoreSaveChangesRequest<DefaultSnapshot>) throws -> DataStoreSaveChangesResult<DefaultSnapshot> { var remappedIdentifiers = [PersistentIdentifier: PersistentIdentifier]() var serializedData = try read() for snapshot in request.inserted { let permanentIdentifier = try PersistentIdentifier.identifier(for: identifier, entityName: snapshot.persistentIdentifier.entityName, primaryKey: UUID()) let permanentSnapshot = snapshot.copy(persistentIdentifier: permanentIdentifier) serializedData[permanentIdentifier] = permanentSnapshot remappedIdentifiers[snapshot.persistentIdentifier] = permanentIdentifier } for snapshot in request.updated { serializedData[snapshot.persistentIdentifier] = snapshot } for snapshot in request.deleted { serializedData[snapshot.persistentIdentifier] = nil } try write(serializedData) return DataStoreSaveChangesResult<DefaultSnapshot>(for: self.identifier, remappedIdentifiers: remappedIdentifiers) } func fetch<T>(_ request: DataStoreFetchRequest<T>) throws -> DataStoreFetchResult<T, DefaultSnapshot> where T : PersistentModel { if request.descriptor.predicate != nil { throw DataStoreError.preferInMemoryFilter } else if request.descriptor.sortBy.count > 0 { throw DataStoreError.preferInMemorySort } let objs = try read() let snapshots = objs.values.map({ $0 }) return DataStoreFetchResult(descriptor: request.descriptor, fetchedSnapshots: snapshots, relatedSnapshots: objs) } func read() throws -> [PersistentIdentifier : DefaultSnapshot] { if FileManager.default.fileExists(atPath: configuration.fileURL.path(percentEncoded: false)) { let decoder = JSONDecoder() decoder.dateDecodingStrategy = .iso8601 let data = try decoder.decode([DefaultSnapshot].self, from: try Data(contentsOf: configuration.fileURL)) var result = [PersistentIdentifier: DefaultSnapshot]() data.forEach { s in result[s.persistentIdentifier] = s } return result } else { return [:] } } func write(_ data: [PersistentIdentifier : DefaultSnapshot]) throws { let encoder = JSONEncoder() encoder.dateEncodingStrategy = .iso8601 encoder.outputFormatting = [.prettyPrinted, .sortedKeys] let jsonData = try encoder.encode(data.values.map({ $0 })) try jsonData.write(to: configuration.fileURL) } } The data model classes: import SwiftData @Model class Settings { private(set) var version = 1 @Relationship(deleteRule: .cascade) var hack: Hack? = Hack() init() { } } @Model class Hack { var foo = "Foo" var bar = 42 init() { } } Container: lazy var mainContainer: ModelContainer = { do { let url = // URL to file let configuration = JSONStoreConfiguration(name: "Settings", schema: Schema([Settings.self, Hack.self]), fileURL: url) return try ModelContainer(for: Settings.self, Hack.self, configurations: configuration) } catch { fatalError("Container error: \(error.localizedDescription)") } }() Load function, that saves a new Settings JSON file if there isn't an existing one: @MainActor func loadSettings() { let mainContext = mainContainer.mainContext let descriptor = FetchDescriptor<Settings>() let settingsArray = try? mainContext.fetch(descriptor) print("\(settingsArray?.count ?? 0) settings found") if let settingsArray, let settings = settingsArray.last { print("Loaded") } else { let settings = Settings() mainContext.insert(settings) do { try mainContext.save() } catch { print("Error saving settings: \(error)") } } } The save operation creates a JSON file, which while it isn't a format I would choose, is acceptable, though I notice that the "hack" property (the relationship) doesn't have the correct identifier. When I run the app again to load the data, I get an error (that there wasn't room to include in this post). Even if I change Apple's code to not assign a new identifier, so the relationship property and its pointee have the same identifier, it still doesn't load. Am I doing something obviously wrong, or are relationships not supported in custom data stores?
2
0
733
Apr ’25
Log Into Apple Account
When a user first downloads my application they are prompted to sign into their apple account via a pop up. I have not had this pop up previously, I believe the change occurred after iOS18. I have functions that do a few things: Retrieves userRecordID Retrieves a userprofile(via userrecordid) from cloudkit.
2
0
443
Mar ’25
Best Practices for Binary Data (“Allows External Storage”) in Core Data with CloudKit Sync
Hello Apple Team, We’re building a CloudKit-enabled Core Data app and would like clarification on the behavior and performance characteristics of Binary Data attributes with “Allows External Storage” enabled when used with NSPersistentCloudKitContainer. Initially, we tried storing image files manually on disk and only saving the metadata (file URLs, dimensions, etc.) in Core Data. While this approach reduced the size of the Core Data store, it introduced instability after app updates and broke sync between devices. We would prefer to use the official Apple-recommended method and have Core Data manage image storage and CloudKit syncing natively. Specifically, we’d appreciate guidance on the following: When a Binary Data attribute is marked as “Allows External Storage”, large image files are stored as separate files on device rather than inline in the SQLite store. How effective is this mechanism in keeping the Core Data store size small on device? Are there any recommended size thresholds or known limits for how many externally stored blobs can safely be managed this way? How are these externally stored files handled during CloudKit sync? Does each externally stored Binary Data attribute get mirrored to CloudKit as a CKAsset? Does external storage reduce the sync payload size or network usage, or is the full binary data still uploaded/downloaded as part of the CKAsset? Are there any bandwidth implications for users syncing via their private CloudKit database, versus developer costs in the public CloudKit database? Is there any difference in CloudKit or Core Data behavior when a Binary Data attribute is managed this way versus manually storing image URLs and handling the file separately on disk? Our goal is to store user-generated images efficiently and safely sync them via CloudKit, without incurring excessive local database bloat or CloudKit network overhead. Any detailed guidance or internal performance considerations would be greatly appreciated. Thank you, Paul Barry Founder & Lead Developer — Boat Buddy / Vessel Buddy iOS App Archipelago Environmental Solutions Inc.
2
0
269
Oct ’25
SwiftData propertiesToFetch question
I have a simple model @Model final class Movie: Identifiable { #Index\<Movie\>(\[.name\]) var id = UUID() var name: String var genre: String? init(name: String, genre: String?) { self.name = name self.genre = genre } } I turned on SQL debugging by including '-com.apple.CoreData.SQLDebug 3' argument on launch. When I fetch the data using the following code, it selects 3 records initially, but then also selects each record individually even though I am not referencing any other attributes. var fetchDescriptor = FetchDescriptor\<Movie\>() fetchDescriptor.propertiesToFetch = \[.id, .name\] fetchDescriptor.fetchLimit = 3 do { print("SELECT START") movies = try modelContext.fetch(fetchDescriptor) print("SELECT END") } catch { print("Failed to load Movie model.") } I see it selecting the 3 rows initially, but then it selects each one separately. Why would it do this on the initial fetch? I was hoping to select the data that I want to display and let the system select the entire record only when I access a variable that I did not initially fetch. CoreData: annotation: fetch using NSSQLiteStatement <0x600002158af0> on entity 'Movie' with sql text 'SELECT 1, t0.Z_PK, t0.ZID, t0.ZNAME FROM ZMOVIE t0 LIMIT 3' returned 3 rows with values: ( "<NSManagedObject: 0x600002158d70> (entity: Movie; id: 0xa583c7ed484691c1 <x-coredata://71E60F4C-1A40-4DB7-8CD1-CD76B4C11949/Movie/p1>; data: <fault>)", "<NSManagedObject: 0x600002158d20> (entity: Movie; id: 0xa583c7ed482691c1 <x-coredata://71E60F4C-1A40-4DB7-8CD1-CD76B4C11949/Movie/p2>; data: <fault>)", "<NSManagedObject: 0x600002158f00> (entity: Movie; id: 0xa583c7ed480691c1 <x-coredata://71E60F4C-1A40-4DB7-8CD1-CD76B4C11949/Movie/p3>; data: <fault>)" ) CoreData: annotation: fetch using NSSQLiteStatement <0x600002154d70> on entity 'Movie' with sql text 'SELECT 0, t0.Z_PK, t0.Z_OPT, t0.ZGENRE, t0.ZID, t0.ZNAME FROM ZMOVIE t0 WHERE t0.Z_PK = ? ' returned 1 rows CoreData: annotation: with values: ( "<NSSQLRow: 0x600000c89500>{Movie 1-1-1 genre=\"Horror\" id=4C5CB4EB-95D7-4DC8-B839-D4F2D2E96ED0 name=\"A000036\" and to-manys=0x0}" ) This all happens between the SELECT START and SELECT END print statements. Why is it fulfilling the faults immediately?
2
0
363
Feb ’25