SwiftData

RSS for tag

SwiftData is an all-new framework for managing data within your apps. Models are described using regular Swift code, without the need for custom editors.

Posts under SwiftData tag

200 Posts

Post

Replies

Boosts

Views

Activity

SwiftData regression in iOS 27.2: inverse relationship not set on children when an uninserted model graph is attached to a persisted model
Since iOS 27.2 (24B119), SwiftData no longer sets the inverse (child → parent) relationship for the children of a model that hasn't been inserted yet when that model is attached to an already-saved model. The children are saved with a nil parent, so the parent's to-many relationship reads back empty. This happens in the same ModelContext and also after reopening the store. The same code works correctly on iOS 27.0 (24A5390f). @Model final class Ledger { @Relationship(deleteRule: .cascade, inverse: \Transaction.ledger) var transactions: [Transaction] = [] } @Model final class Transaction { var ledger: Ledger? @Relationship(deleteRule: .cascade, inverse: \Item.transaction) var items: [Item] = [] init(items: [Item]) { self.items = items } } @Model final class Item { var transaction: Transaction? } // Inside a @ModelActor; `ledger` is fetched and already saved. let transaction = Transaction(items: [Item(), Item()]) // not inserted ledger.transactions.append(transaction) // iOS 27.0: item.transaction === transaction for every item // iOS 27.2: item.transaction == nil for every item try modelContext.save() // iOS 27.2: transaction.items.count == 0 (expected 2); both items are orphaned rowsThe inverse is already nil before save(), so this isn't a save or flush problem. The link just isn't set when the graph is attached. Affected patterns on 27.2 • persisted.list.append(uninsertedParentWithChildren) • persisted.list[index] = uninsertedParentWithChildren • Reassigning persisted.list = [...] when the new models have their own child arrays (grandchildren end up orphaned) • Models with several to-many arrays of the same child type Not affected • A graph that's entirely new, including the root • To-one relationships set in init • Models inserted into the context before the relationship is set Toolchain ruled out. I built the repro on the same iPhone 13 (iOS 27.2) with three toolchains: xcode 26.6, 27.1 and 27.2 Workaround. Insert the children and set the inverse explicitly before saving: modelContext.insert(transaction) for item in transaction.items { modelContext.insert(item) item.transaction = transaction } ledger.transactions.append(transaction) try modelContext.save()You have to do this at every level, grandchildren included. Has anyone else seen this on 27.2? And can someone from the SwiftData team confirm whether this is an intended behavior change or a regression? Feedback: FB25355425 (includes a standalone repro project, reports from iOS 27.0 and 27.2, and a sysdiagnose)
0
0
210
1d
SwiftData and iCloud Backup — Protecting Sensitive Local Data
I'm developing SipBudget, an iPhone app that will store manually entered alcohol-consumption records locally using SwiftData. The app will not use CloudKit synchronization, HealthKit, or a developer-operated cloud database. I understand that App Review Guideline 5.1.3(ii) prohibits storing personal health information in iCloud. I would appreciate technical guidance on two questions: Can a local SwiftData database be reliably excluded from ordinary iCloud device backups? If so, what is Apple's recommended implementation for ensuring that the database and related files remain excluded, including after database updates or migrations? I'm asking before implementation so I can design the storage architecture correctly. Thank you.
1
0
121
4d
How do deal with NavigationSplitView not saving selection on iPhone
I have a detail view that has a @Binding var Thing, which is passed to it from the parent. It has TextFields that need to use that bound object's fields. // Using this to pass the selection around @Observable class AppSelection { var selectedThings:Set<Thing> = Set(); } struct ContentView: View { @State private var selectionStore = AppSelection(); var body: some View { NavigationSplitView { ... } content: { ...list that sets the selectionStore.selectedThings... } detail: { if !selectionStore.selectedThings.isEmpty { DetailView(thing:Binding( get: { selectionStore.selectedThings.first! }, // Crashes here set: { selectionStore.selectedThings = [$0] } )) .frame(maxHeight:.infinity, alignment:.top) } else { Text("Select a thing."); } } } } struct DetailView:View { @Binding var thing:Thing; var body:some View { TextField("Blah", $thing.name); TextField("Blerg", $thing.stuff); } }A crash happens when I navigate back from the DetailView in the line commented as such. I assume the NavigationSplitView is resetting the selection back to an empty state. Why the Binding given to the DetailView is even trying to get its value at that point is beyond me (so much weirdness in SwiftUI). I've taken so many different stabs at trying to make things work differently, but I just don't understand enough about SwiftUI. Like can I make the DetailView take an optional binding? If the Thing is nil, then all the TextFields complain that they require a non-optional binding. I don't even want to show the Detail view if nothing is selected (hence the "Select a thing.").
0
0
642
1w
modelContainer in SwiftData
Hello, In SwiftUI within Swift Playgrounds on iPad, I get two different results depending on whether I place .modelContainer(for: Valeur.self) immediately after ContentView() or after WindowGroup {....}. If I place it after WindowGroup {....}, I can neither save to nor query the database in the preview; it only works in read-only mode. If I place it after ContentView(), it works correctly in both preview and read-write mode. Which version should I use? Thanks for your feedback.
3
0
278
1w
SwiftData Model object added to multiple parent objects moves ownership to only last parent
I thought an object could be added to as many other parents as I wanted, but now it's not behaving. @Model final class Genre { var name:String; init(name:String) { self.name = name; } } @Model final class Disc { var genre:Array<Genre> = []; }Then elsewhere I made sure the user is not creating a duplicate Genre before adding either the existing one or a new one: struct BlahView: View { @Query var allGenres:[Genre]; var theseGenres; // Pretend this is actually assigned. var body: some View { if let idx = allGenres.firstIndex(where: { genr in genr.name == editStr; }) { theseGenres.append(allGenres[idx]); } else { theseGenres.append(Genre(name:editStr)); } } }When the genre gets added to the 2nd parent, it goes away in the 1st parent it was added to. I initially used the #Unique<Genre>([\.name]) thingy in Genre, but then read that it does not work when the data is stored in CloudKit, which I'm doing. Hence the check for existing I'm doing.
1
0
353
1w
Binding Picker to enum value in SwiftData struct
I have a SwiftData @Model class that has a var of Media. enum Media: String, CaseIterable, Identifiable, Codable { case dvd = "DVD" case bluray = "Blu-ray" case bluray4k = "Blu-ray 4k" var id:String { self.rawValue } } In one of my views, I'm trying to show a Picker with the enum values, and then bind the @Model's field to the Picker's selection. I've been trying all kinds of things from suggesting I'm finding online. Here's a poorly pasted version of what my last attempt looks like (I'm sure I have the wrong number of closing curly brackets, but just ignore that): struct DetailView: View { @Binding var item:Item; // The @Model class. @State private var selectedMedia:Media = .dvd; var body:some View { Picker("Media", selection:$selectedMedia) { ForEach(Media.allCases, id:\.self) { media in Text(media.rawValue); } } .labelsHidden() .onAppear() { selectedMedia = item.media; } .onChange(of:selectedMedia) { oldValue, newValue in item.media = selectedMedia; } } } What's a good way to make this work? Am I going to have to use a custom formatter of some type, bind the Picker to a string, and convert the selected value with the formatter?
1
0
395
2w
SwiftData: "backing data was detached from a context without resolving attribute faults" when deleting a model shown in a @Query driven list
A dashboard screen lists cameras from a @Query. Each row is a child view that holds the model instance: @Query(filter: #Predicate { $0.device?.isSelected == true }) private var cameras: [CameraModel] List { ForEach(cameras) { camera in CameraCellView(camera: camera) //holds let camera: CameraModel } } The row reads model attributes in its body (camera.name, camera.cameraType, camera.thumbnailData). It also has a 1-second timer that updates a "last snapshot" subtitle, so it redraws on its own. A settings screen is pushed on top of the dashboard in the same NavigationStack. It deletes a camera like this: camera.modelContext?.delete(camera) try? camera.modelContext?.save() Immediately after the delete, the app crashes in the dashboard row's body when it reads an attribute: Fatal error: This backing data was detached from a context without resolving attribute faults: PersistentIdentifier(...) - \CameraModel.cameraType This is not 100% reproducible. The whole error message is: Thread 1: Fatal error: This backing data was detached from a context without resolving attribute faults: PersistentIdentifier(id: SwiftData.PersistentIdentifier.ID(backing: SwiftData.PersistentIdentifier.PersistentIdentifierBacking.managedObjectID(0x8f8ff6c009fee652 x-coredata://65230C45-6F86-4B64-AEAB-6AAA9CB72D24/CameraModel/p16))) - \CameraModel.cameraType I understand this is due to a small gap where the SwiftUI view is rerendered before Query updates the view because of the deletion and the SwiftUI view points at a nonexistent SwiftData record. I'm just wondering what's a good way of avoiding that? SwiftData is used project-wide so this can potentially happen on nearly every view.
0
0
104
3w
CKShare recipient continues using stale permissions after authorization record is updated in Production CloudKit
I am developing an iOS/iPadOS app using SwiftUI, SwiftData, CloudKit, and CKShare. I need help determining why an already-approved CKShare recipient is not receiving updated application-level authorization. Architecture The owner stores working data locally in SwiftData and explicitly mirrors shared data into a custom CloudKit zone named AthleteVaultSharedSchoolData. The owner writes these records to privateCloudDatabase. Recipients accept a zone-wide CKShare and read the accepted zone through sharedCloudDatabase. Each approved recipient also has an AVSchoolMembershipAuthorization record in that shared zone. Its deterministic record name is based on the recipient's CloudKit user record ID: AVSchoolMembershipAuthorization- The authorization contains the recipient's role and arrays of permitted team, sport, and player UUIDs. What works The recipient successfully accepted the share and can download the shared school data. The recipient has previously fetched his authorization from the accepted shared zone and received the correct initial permissions. The owner can change that recipient's permissions and save the updated authorization. I verified in CloudKit Console → Production → Private Database that there is exactly one authorization record for this recipient. It is active and contains the newly selected playerIDs. The record's updatedAt also changes when the administrator saves the permissions. Both owner and recipient are testing the same TestFlight Production build. The problem After changing an already-approved recipient's permissions, the Production authorization record is correct, but the recipient continues operating with the previous player permissions after closing and reopening the app. For example, the administrator removes Player A and grants Player B. CloudKit Console shows the authorization now contains Player B instead of Player A, but the recipient continues seeing Player A and does not see Player B. On the recipient I obtain the current CloudKit user record ID, locate the accepted shared zone, construct the deterministic authorization record ID, and fetch it from the shared database: let recordID = CKRecord.ID( recordName: "AVSchoolMembershipAuthorization-(userRecordID.recordName)", zoneID: acceptedZoneID ) container.sharedCloudDatabase.fetch(withRecordID: recordID) { record, error in // decode current authorization } Once the authorization is returned, the app explicitly reconciles its local SwiftData permission rows: permissions absent from the current authorization are deleted and newly granted permissions are inserted. Production schema During troubleshooting I discovered that AVSchoolMembershipAuthorization had initially existed only in Development. That schema has now been deployed to Production. Before deployment, Production correctly returned a “Cannot create new type AVSchoolMembershipAuthorization in production schema” error. After deploying the schema, the owner save succeeds and the updated authorization is visible directly in the Production CloudKit Console. Therefore the current problem occurs after the Production authorization has been successfully saved. Questions With a zone-wide CKShare, should records created or modified in the owner's shared custom zone automatically become visible to an already-accepted participant through sharedCloudDatabase? If AVSchoolMembershipAuthorization was created after the recipient originally accepted the zone-wide share, is any additional operation required to expose that record to the existing participant? Is sharedCloudDatabase.fetch(withRecordID:), using the accepted shared-zone ID and exact deterministic record ID, the appropriate way to retrieve the latest server version? Can an accepted participant continue receiving an older version of a record after the owner successfully saves a newer version to the Production private database? If so, what API or synchronization pattern should be used to reliably obtain the current version? When changing CKShare.Participant.permission for an existing participant at the same time as changing application-level authorization in a custom CKRecord, is there another CKShare operation required? Is a per-recipient authorization CKRecord inside a zone-wide shared zone an appropriate CloudKit design, or is there a recommended pattern for per-recipient authorization? I can provide the relevant CloudKit service code, CloudKit Console screenshots, and additional diagnostics if needed. Thank you for any guidance on the expected CloudKit behavior for updated records in an already-accepted zone-wide CKShare.
0
0
185
4w
NSPersistentCloudKitContainer export permanently blocked: RecordDelete fails with BAD_REQUEST on _pcs_data, even after fresh install
Our SwiftData app (NSPersistentCloudKitContainer under the hood, Production environment, iOS 27.0, private database, default zone com.apple.coredata.cloudkit.zone, no sharing) can no longer export for one user account. On every launch, the first export is a RecordDelete of duplicate records (CD_HealthMetricsSnapshot / CD_DailyLog) that our deduplication removed locally. The CloudKit Console shows it failing with overallStatus: USER_ERROR, error: BAD_REQUEST, returnedRecordTypes: "_pcs_data". On device it surfaces as CKErrorDomain Code=2 "CKInternalErrorDomain: 1011" (partialFailure). After that, NSCloudKitMirroringDelegate reports "Never successfully initialized" and no further export happens in that process. Imports still succeed. It reproduces after deleting and reinstalling the app. On a fresh install, the initial import succeeds, and the very first export, deleting records that were only downloaded and never modified locally, fails the same way. Earlier delete batches from the same deduplication on the same account succeeded, so it seems tied to specific records or the zone's PCS state. Request IDs: E49E4252-99A6-4103-8C03-1D0738005AA3, 4BA5133D-A1F5-423F-BDE6-F65B76B66375, E8D27548-BED1-49A4-9214-3C1A35CDC8C7. Container: iCloud.com.backbonesvc.fastsignal.ios. Questions: What causes a RecordDelete to fail with BAD_REQUEST on _pcs_data? Is there a supported way to clear this without purging the zone? purgeObjectsAndRecordsInZone is documented to also delete local objects, which we must avoid. Can Apple inspect or repair the server-side state for these request IDs?
0
0
172
4w
Which technology should be used to save configuration information?
I want to save some configure information for my app. Which technology should be used to save configuration information? SwiftData or a json file? I'm not sure whether it's appropriate to use SwiftData.It seems that SwiftData is suitable for saving multiple data of the same type, such as saving multiple student information. If I use SwiftData to save a configuration information, there may be the following code in the place where it is used: @query private var configs:[ConfigInfo] … name = configs[0].name If there are other ways to implement it, please let me know. Thanks.
1
0
337
Sep ’26
CloudKit Production sync fails with CKInternalErrorDomain 1011 and BAD_REQUEST on _pcs_data
Hi, I’m seeing a CloudKit Production sync failure in an iOS app using SwiftData/Core Data with private CloudKit mirroring. Sync worked correctly after release, then stopped working without any new app build being released. Device logs show: CKInternalErrorDomain Code=1011 and Core Data reports that CloudKit mirroring was never successfully initialized. CloudKit Production logs also show a native PRIVATE database request failing with: USER_ERROR / BAD_REQUEST involving the internal record type: _pcs_data The Production schema, private zone, and subscription are still present. I have not reset Production or deleted any zones/subscriptions. I have already filed a Feedback Assistant report with diagnostics. Has anyone seen this pattern before? Is there a safe developer-side remediation, or is this typically an Apple-side CloudKit/PCS issue? I want to avoid any destructive action that could risk existing user data.
2
0
531
Sep ’26
SwiftData with CloudKit Error: Error updating background task request
Hi, Overview I have a SwiftData project which automatically syncs with CloudKit. When I run the app, I see the following error in Xcode logs. Error updating background task request: Error Domain=BGSystemTaskSchedulerErrorDomain Code=3 "(null)" My attempt I can enable Background processing (under Signing & Capabilities > Background modes), but I don't know the BGTaskSchedulerPermittedIdentifiers to add in the Info.plist Questions How can I resolve this? If I should enable background processing, what are the BGTaskSchedulerPermittedIdentifiers to add in Info.plist?
19
0
2.6k
Sep ’26
SwiftData predicate with optional chaining failing on OS 27
The following predicate (which returns results on OS 26) only returns results on OS 27 when I comment out the last line: reviewDescriptor = FetchDescriptor<Flashcard>( predicate: #Predicate { $0.sourceLanguageRaw == rawLang && $0.cardStateRaw == reviewRaw && $0.dueDate < currentDate && !$0.isSuspended && advancedStudyEnabled.evaluate($0) && !($0.promotionLog?.isProcessing ?? false) // <- here }, sortBy: [SortDescriptor(\.previousInterval)] ) // where Flashcard — PromotionLog is a one-to-one optional relationship Because I’m still getting results on OS 26 from the same data, my guess is the line with optional chaining somehow causes the entire predicate to fail silently, without crashing the app. But I also don’t see any posts about it, so maybe it’s something I’m doing wrong? Is anyone else experiencing this? Any workarounds? ETA: However, this chaining appears to be working just fine: reviewDescriptor.predicate = #Predicate<Flashcard> { $0.sourceLanguageRaw == rawLang && $0.cardStateRaw == reviewRaw && ($0.pronunciationLog?.dueDate ?? currentDate) < currentDate && $0.pronunciationLog?.practiceStateRaw != masteredRaw && !$0.isSuspended } So I’m a bit lost. Maybe the syntax of the first? Something about using it alongside .evaluate()? ETA2: After a bit more debugging, when && !($0.promotionLog?.isProcessing ?? false) is commented out, a Flashcard where promotionLog == nil shows up. But if promotionLog == nil, the line should evaluate to !(false), i.e. true. So why would that line stop the card from showing up in the first place?
1
0
286
Sep ’26
ShieldConfigurationExtension & SwiftData
Hi, I am developing a Screen Time App and I am having issues with the ShieldConfigurationExtension (ShieldConfigurationDataSource). I know this extensions is sandboxed but I should be able to read data from the main app. I am using SwiftData as my database, but I am unable to initialize it in the extensions with an error indicating insufficient file permissions. I have App Group set up and I am able to share data using UserDefaults but that is just inconvenient. Is there any way I could just open the SwiftData in read only mode so that I could display the user some info on the shield? SwiftData Init: private func setupContainer() throws { let schema = Schema([ DogEntity.self, HouseEntity.self ]) // Use app group container if available let config: ModelConfiguration if let containerURL = FileManager.default.containerURL( forSecurityApplicationGroupIdentifier: "group.\(Bundle.app.bundleIdentifier ?? "")" ) { config = ModelConfiguration(schema: schema, url: containerURL.appendingPathComponent("default.sqlite")) } else { config = ModelConfiguration(schema: schema) } self.container = try ModelContainer(for: schema, configurations: [config]) } Error in extension: fault: Attempt to add read-only file at path file:///private/var/mobile/Containers/Shared/AppGroup/51431199-5919-4AE6-940C-6FE3C53EEB46/default.sqlite read/write. Adding it read-only instead. This will be a hard error in the future; you must specify the NSReadOnlyPersistentStoreOption. error: (3) access permission denied error: Encountered exception error during prepareSQL for SQL string 'SELECT TBL_NAME FROM SQLITE_MASTER WHERE TBL_NAME = 'Z_METADATA'' : access permission denied with userInfo { NSFilePath = "/private/var/mobile/Containers/Shared/AppGroup/51431199-5919-4AE6-940C-6FE3C53EEB46/default.sqlite"; NSSQLiteErrorDomain = 3; } while checking table name from store: <NSSQLiteConnection: 0x154100300> error: Store failed to load. <NSPersistentStoreDescription: 0x15402d590> (type: SQLite, url: file:///private/var/mobile/Containers/Shared/AppGroup/51431199-5919-4AE6-940C-6FE3C53EEB46/default.sqlite) with error = Error Domain=NSCocoaErrorDomain Code=256 "The file “default.sqlite” couldn’t be opened." UserInfo={NSFilePath=/private/var/mobile/Containers/Shared/AppGroup/51431199-5919-4AE6-940C-6FE3C53EEB46/default.sqlite, NSSQLiteErrorDomain=3} with userInfo { NSFilePath = "/private/var/mobile/Containers/Shared/AppGroup/51431199-5919-4AE6-940C-6FE3C53EEB46/default.sqlite"; NSSQLiteErrorDomain = 3; } Any help appreciated 🙂
2
0
390
Sep ’26
HistoryObserver eventCounter updating 9-16 times per app launch because of CloudKit syncing?
I created a finance tracking app. I wanted to use HistoryObserver to determine when Transactions are created/updated/deleted on another device with the same appleId, so I can update some charts I have an @Observable model that has this (simplified) setup: private(set) var transactionObserver: HistoryObserver? func setupHistoryObserver(modelContainer: ModelContainer) throws { transactionObserver = try HistoryObserver( observedModels: [Transaction.self], modelContainer: modelContainer, ) } var transactionUpdateTrigger: Int { transactionObserver?.eventCounter ?? 0 } I have the view setup with: .task(id: viewModel.transactionUpdateTrigger) { print("updating chart data: \(viewModel.transactionUpdateTrigger)") await updateChartData() } When I launch my app on my iPhone, I see: updating chart data: 0 updating chart data: 1 updating chart data: 2 updating chart data: 3 updating chart data: 4 updating chart data: 5 updating chart data: 6 updating chart data: 7 updating chart data: 8 updating chart data: 9 updating chart data: 10 On simulator, it only fires once: updating chart data: 0 The docs state: "When relevant changes are detected, the observer updates its eventCounter property." The happens every single time I try deploying my app to my iPhone on iOS 27 beta 8, but with varying numbers of eventCounter increments. I only have the app installed on a single device with my Apple Account. Why is this happening? There should be no changes to my models, as is clear because there's no issues when running this in simulator.
2
0
621
Sep ’26
#Predicate needs better validation
Hi, Overview I am finding #Predicate to be a bit tricky when used with Swift Data It compiles fine but crashes at runtime I know the fix for the problem just wondering if such pitfalls can be avoided at compile time Exception *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'can't use NULL on left hand side' terminating due to uncaught exception of type NSException CoreData: error: SQLCore dispatchRequest: exception handling request: <NSSQLFetchRequestContext: 0x11209b000> , can't use NULL on left hand side with userInfo of (null) Questions Could anything be done to improve the safety to avoid such issues at runtime? Could I write the code better (better than the fix below) to avoid this? My thoughts Fix is possible however it wasn't obvious to me that there was a problem with my original code Would be nice to prevent them at compile time if possible. Currently got to be really careful to avoid such crashes. Code import Foundation import SwiftData @Model class Car { var name: String var modelRawValue: String? init(name: String, modelRawValue: String?) { self.name = name self.modelRawValue = modelRawValue } } enum CarModel: String, CaseIterable { case modelA case modelB } func makePredicate(filterModels: [CarModel]?) -> Predicate<Car> { let filterRawValues = filterModels?.map { $0.rawValue } let predicate = #Predicate<Car> { car in if let filterRawValues { if let carModelRawValue = car.modelRawValue { filterRawValues.contains(carModelRawValue) } else { false } } else { true } } return predicate } func fetch(context: ModelContext) throws { let predicate = makePredicate(filterModels: nil) let fetchDescriptor = FetchDescriptor(predicate: predicate) do { let cars = try context.fetch(fetchDescriptor) print(cars.count) } catch { print("Error: \(error)") throw error } } Fix func makePredicate(filterModels: [CarModel]?) -> Predicate<Car> { // Checking nil condition even before creating the predicate fixes the issue guard let filterModels else { return .true } let filterRawValues = filterModels.map { $0.rawValue } let predicate = #Predicate<Car> { car in if let carModelRawValue = car.modelRawValue { filterRawValues.contains(carModelRawValue) } else { false } } return predicate }
3
0
706
Sep ’26
Migrating a Transformable attribute from CoreData to SwiftData
I am migrating a CloudKit-synchronized multi-platform app from CoreData to SwiftData. (Xcode 27.0 beta 5). One of my Models/Entities contains a Transformable attribute, which is defined in the CoreData model editor as: and which is defined in the generated CoreData class as @NSManaged nonisolated public var authorNames: [String]? Using the built-in translation took, Xcode created a Model wich included @Attribute(.transformable(by: "NSSecureUnarchiveFromDataTransformerName")) var authorNames: [String] = [] This compiles but does not run. In the function func getModelContainer() throws -> ModelContainer { let storeURL = try FileManager.default.url( for: .applicationSupportDirectory, in: .userDomainMask, appropriateFor: nil, create: true) .appendingPathComponent(dbName) let modelConfiguration = ModelConfiguration( schema: dbSchema, url: storeURL, cloudKitDatabase: .automatic) let container = try ModelContainer( for: dbSchema, migrationPlan: MigrationPlan.self, configurations: [modelConfiguration]) return container } the app throws a fatal error in the ModelContainer initializer, SwiftData/SchemaCoreData.swift:398: Fatal error: Application must register a ValueTransformer for NSSecureUnarchiveFromDataTransformerName So I added the following line of code at the top of this function: ValueTransformer.setValueTransformer( NSSecureUnarchiveFromDataTransformer(), forName: .secureUnarchiveFromDataTransformerName) which also compiles but also throws the same fatal error in the same place. Can anyone suggest how to resolve this problem? This is a CloudKit synchronized app, so I am constrained in what I can do with this attribute.
1
0
309
Aug ’26
Issue with SwiftData migration and renaming property when using @Attribute(originalName:)
Put simply, @Attribute(originalName:) doesn't seem to work. I'm getting "Validation error missing attribute values on mandatory destination relationship". Tried with Xcode 26.6 on iOSes 18.6 and 26.5, and with Xcode 27 on iOS27. Same result. Original Schema: typealias CurrentSchemaModel = SchemaV100 typealias House = CurrentSchemaModel.House typealias Automobile = CurrentSchemaModel.Automobile enum SchemaV100: VersionedSchema { static let versionIdentifier: Schema.Version = .init(1, 0, 0) static var models: [any PersistentModel.Type] { [Automobile.self, House.self] } @Model final class Automobile { var id: UUID = UUID() var name: String = "" init(name: String) { self.name = name } } @Model final class House { var id: UUID = UUID() var name: String = "" var automobile: Automobile var createdDate: Date = Date() init(name: String, automobile: Automobile) { self.name = name self.automobile = automobile } } } Updated Schema (renamed House.automobile to House.automobileOne): typealias CurrentSchemaModel = SchemaV101 /*updated from SchemaV100 */ enum SchemaV101: VersionedSchema { static let versionIdentifier: Schema.Version = .init(1, 0, 1) static var models: [any PersistentModel.Type] { [Automobile.self, House.self] } @Model final class Automobile { var id: UUID = UUID() var name: String = "" init(name: String) { self.name = name } } @Model final class House { var id: UUID = UUID() var name: String = "" @Attribute(originalName: "automobile") var automobileOne: Automobile var createdDate: Date = Date() init(name: String, automobileOne: Automobile) { self.name = name self.automobileOne = automobileOne } } } Migration Plan: enum TestRenameMigrationPlan: SchemaMigrationPlan { static var schemas: [any VersionedSchema.Type] { let currentSchemas: [any VersionedSchema.Type] = [SchemaV100.self, SchemaV101.self] return currentSchemas } static var stages: [MigrationStage] { [migrateV100toV101] } // MARK: - V101 static let migrateV100toV101 = MigrationStage.lightweight(fromVersion: SchemaV100.self, toVersion: SchemaV101.self) } SQLDebug logging shows this: CoreData: sql: ALTER TABLE ZHOUSE RENAME TO _T_ZHOUSE CoreData: sql: CREATE TABLE ZHOUSE ( Z_PK INTEGER PRIMARY KEY, Z_ENT INTEGER, Z_OPT INTEGER, ZAUTOMOBILEONE INTEGER, ZCREATEDDATE TIMESTAMP, ZNAME VARCHAR, ZID BLOB ) CoreData: sql: INSERT INTO ZHOUSE (Z_PK,Z_ENT,Z_OPT,ZAUTOMOBILEONE,ZCREATEDDATE,ZNAME,ZID) SELECT Z_PK,Z_ENT,Z_OPT,?,ZCREATEDDATE,ZNAME,ZID FROM _T_ZHOUSE CoreData: details: SQLite bind[0] = nil Seems excessive to recreate table for a simple column rename, but I digress... The curious part is the binding, SQLite bind[0] = nil, where I'd expect the originalName value (e.g. ZAUTOMOBILE) to be used. Any thoughts or explanations would be appreciated. Steve
0
0
84
Aug ’26
How do I write this #Predicate?
I have two Models which are defined (simplified) as follows: @Model final class Book { var id: UUID = UUID() var title: String = "" var authors: [Author]? = [] } @Model final class Author { var id: UUID = UUID() var name: String "" @Relationship(inverse: \Book.authors) var books: [Book]? = [] } Both Book.authors and Author.books are defined as optionals to satisfy the requirements of CloudKit, although it is clear from the above that neither is ever actually nil. I am trying to write a #Predicate that finds objects of type Book with a title that matches a specified title and with an author that matches a specified author. The function I'd like to write looks something like this: func find(title: String, author: Author, with context: ModelContext) -> Book? { let same = ComparisonResult.orderedSame let predicate = #Predicate<Book> { book in book.title.caseInsensitiveCompare(title) == same && book.authors!.contains(where: { $0.id == author.id }) } let descriptor = FetchDescriptor<Book>(predicate: predicate) return try? context.fetch(descriptor).first } This function fails to compile inside the expansion of the #Predicate macro with a very long error message: Cannot convert value of type (a long 'PredicateExpresions....') (aka (another log 'PredicateExpressions....')) to closure result type 'any StandardPredicateExpression<Bool>' I don't understand. How can I write this predicate so that it will both compile and work? I know how to work around this problem, but would like to both deepen my understanding of Swift and SwiftData and to avoid the (inelegant) workaround.
2
0
506
Aug ’26
Sandboxed macOS app using SwiftData and CloudKit cannot initialize CloudKit mirroring.
I have a Mac and iOS app intended to sync data in iCloud. Both apps in TestFlight, the iOS reads and writes to iCloud but the Mac fails as the App Sandbox denies mach-lookup com.apple.cloudd, so NSCloudKitMirroringDelegate` never reaches the daemon and setup fails permanently. I have a minimal app reproducing the issue on for the Mac app. I also submitted a feedback FB24450529
1
0
754
Aug ’26
SwiftData regression in iOS 27.2: inverse relationship not set on children when an uninserted model graph is attached to a persisted model
Since iOS 27.2 (24B119), SwiftData no longer sets the inverse (child → parent) relationship for the children of a model that hasn't been inserted yet when that model is attached to an already-saved model. The children are saved with a nil parent, so the parent's to-many relationship reads back empty. This happens in the same ModelContext and also after reopening the store. The same code works correctly on iOS 27.0 (24A5390f). @Model final class Ledger { @Relationship(deleteRule: .cascade, inverse: \Transaction.ledger) var transactions: [Transaction] = [] } @Model final class Transaction { var ledger: Ledger? @Relationship(deleteRule: .cascade, inverse: \Item.transaction) var items: [Item] = [] init(items: [Item]) { self.items = items } } @Model final class Item { var transaction: Transaction? } // Inside a @ModelActor; `ledger` is fetched and already saved. let transaction = Transaction(items: [Item(), Item()]) // not inserted ledger.transactions.append(transaction) // iOS 27.0: item.transaction === transaction for every item // iOS 27.2: item.transaction == nil for every item try modelContext.save() // iOS 27.2: transaction.items.count == 0 (expected 2); both items are orphaned rowsThe inverse is already nil before save(), so this isn't a save or flush problem. The link just isn't set when the graph is attached. Affected patterns on 27.2 • persisted.list.append(uninsertedParentWithChildren) • persisted.list[index] = uninsertedParentWithChildren • Reassigning persisted.list = [...] when the new models have their own child arrays (grandchildren end up orphaned) • Models with several to-many arrays of the same child type Not affected • A graph that's entirely new, including the root • To-one relationships set in init • Models inserted into the context before the relationship is set Toolchain ruled out. I built the repro on the same iPhone 13 (iOS 27.2) with three toolchains: xcode 26.6, 27.1 and 27.2 Workaround. Insert the children and set the inverse explicitly before saving: modelContext.insert(transaction) for item in transaction.items { modelContext.insert(item) item.transaction = transaction } ledger.transactions.append(transaction) try modelContext.save()You have to do this at every level, grandchildren included. Has anyone else seen this on 27.2? And can someone from the SwiftData team confirm whether this is an intended behavior change or a regression? Feedback: FB25355425 (includes a standalone repro project, reports from iOS 27.0 and 27.2, and a sysdiagnose)
Replies
0
Boosts
0
Views
210
Activity
1d
SwiftData and iCloud Backup — Protecting Sensitive Local Data
I'm developing SipBudget, an iPhone app that will store manually entered alcohol-consumption records locally using SwiftData. The app will not use CloudKit synchronization, HealthKit, or a developer-operated cloud database. I understand that App Review Guideline 5.1.3(ii) prohibits storing personal health information in iCloud. I would appreciate technical guidance on two questions: Can a local SwiftData database be reliably excluded from ordinary iCloud device backups? If so, what is Apple's recommended implementation for ensuring that the database and related files remain excluded, including after database updates or migrations? I'm asking before implementation so I can design the storage architecture correctly. Thank you.
Replies
1
Boosts
0
Views
121
Activity
4d
How do deal with NavigationSplitView not saving selection on iPhone
I have a detail view that has a @Binding var Thing, which is passed to it from the parent. It has TextFields that need to use that bound object's fields. // Using this to pass the selection around @Observable class AppSelection { var selectedThings:Set<Thing> = Set(); } struct ContentView: View { @State private var selectionStore = AppSelection(); var body: some View { NavigationSplitView { ... } content: { ...list that sets the selectionStore.selectedThings... } detail: { if !selectionStore.selectedThings.isEmpty { DetailView(thing:Binding( get: { selectionStore.selectedThings.first! }, // Crashes here set: { selectionStore.selectedThings = [$0] } )) .frame(maxHeight:.infinity, alignment:.top) } else { Text("Select a thing."); } } } } struct DetailView:View { @Binding var thing:Thing; var body:some View { TextField("Blah", $thing.name); TextField("Blerg", $thing.stuff); } }A crash happens when I navigate back from the DetailView in the line commented as such. I assume the NavigationSplitView is resetting the selection back to an empty state. Why the Binding given to the DetailView is even trying to get its value at that point is beyond me (so much weirdness in SwiftUI). I've taken so many different stabs at trying to make things work differently, but I just don't understand enough about SwiftUI. Like can I make the DetailView take an optional binding? If the Thing is nil, then all the TextFields complain that they require a non-optional binding. I don't even want to show the Detail view if nothing is selected (hence the "Select a thing.").
Replies
0
Boosts
0
Views
642
Activity
1w
modelContainer in SwiftData
Hello, In SwiftUI within Swift Playgrounds on iPad, I get two different results depending on whether I place .modelContainer(for: Valeur.self) immediately after ContentView() or after WindowGroup {....}. If I place it after WindowGroup {....}, I can neither save to nor query the database in the preview; it only works in read-only mode. If I place it after ContentView(), it works correctly in both preview and read-write mode. Which version should I use? Thanks for your feedback.
Replies
3
Boosts
0
Views
278
Activity
1w
SwiftData Model object added to multiple parent objects moves ownership to only last parent
I thought an object could be added to as many other parents as I wanted, but now it's not behaving. @Model final class Genre { var name:String; init(name:String) { self.name = name; } } @Model final class Disc { var genre:Array<Genre> = []; }Then elsewhere I made sure the user is not creating a duplicate Genre before adding either the existing one or a new one: struct BlahView: View { @Query var allGenres:[Genre]; var theseGenres; // Pretend this is actually assigned. var body: some View { if let idx = allGenres.firstIndex(where: { genr in genr.name == editStr; }) { theseGenres.append(allGenres[idx]); } else { theseGenres.append(Genre(name:editStr)); } } }When the genre gets added to the 2nd parent, it goes away in the 1st parent it was added to. I initially used the #Unique<Genre>([\.name]) thingy in Genre, but then read that it does not work when the data is stored in CloudKit, which I'm doing. Hence the check for existing I'm doing.
Replies
1
Boosts
0
Views
353
Activity
1w
Binding Picker to enum value in SwiftData struct
I have a SwiftData @Model class that has a var of Media. enum Media: String, CaseIterable, Identifiable, Codable { case dvd = "DVD" case bluray = "Blu-ray" case bluray4k = "Blu-ray 4k" var id:String { self.rawValue } } In one of my views, I'm trying to show a Picker with the enum values, and then bind the @Model's field to the Picker's selection. I've been trying all kinds of things from suggesting I'm finding online. Here's a poorly pasted version of what my last attempt looks like (I'm sure I have the wrong number of closing curly brackets, but just ignore that): struct DetailView: View { @Binding var item:Item; // The @Model class. @State private var selectedMedia:Media = .dvd; var body:some View { Picker("Media", selection:$selectedMedia) { ForEach(Media.allCases, id:\.self) { media in Text(media.rawValue); } } .labelsHidden() .onAppear() { selectedMedia = item.media; } .onChange(of:selectedMedia) { oldValue, newValue in item.media = selectedMedia; } } } What's a good way to make this work? Am I going to have to use a custom formatter of some type, bind the Picker to a string, and convert the selected value with the formatter?
Replies
1
Boosts
0
Views
395
Activity
2w
SwiftData: "backing data was detached from a context without resolving attribute faults" when deleting a model shown in a @Query driven list
A dashboard screen lists cameras from a @Query. Each row is a child view that holds the model instance: @Query(filter: #Predicate { $0.device?.isSelected == true }) private var cameras: [CameraModel] List { ForEach(cameras) { camera in CameraCellView(camera: camera) //holds let camera: CameraModel } } The row reads model attributes in its body (camera.name, camera.cameraType, camera.thumbnailData). It also has a 1-second timer that updates a "last snapshot" subtitle, so it redraws on its own. A settings screen is pushed on top of the dashboard in the same NavigationStack. It deletes a camera like this: camera.modelContext?.delete(camera) try? camera.modelContext?.save() Immediately after the delete, the app crashes in the dashboard row's body when it reads an attribute: Fatal error: This backing data was detached from a context without resolving attribute faults: PersistentIdentifier(...) - \CameraModel.cameraType This is not 100% reproducible. The whole error message is: Thread 1: Fatal error: This backing data was detached from a context without resolving attribute faults: PersistentIdentifier(id: SwiftData.PersistentIdentifier.ID(backing: SwiftData.PersistentIdentifier.PersistentIdentifierBacking.managedObjectID(0x8f8ff6c009fee652 x-coredata://65230C45-6F86-4B64-AEAB-6AAA9CB72D24/CameraModel/p16))) - \CameraModel.cameraType I understand this is due to a small gap where the SwiftUI view is rerendered before Query updates the view because of the deletion and the SwiftUI view points at a nonexistent SwiftData record. I'm just wondering what's a good way of avoiding that? SwiftData is used project-wide so this can potentially happen on nearly every view.
Replies
0
Boosts
0
Views
104
Activity
3w
CKShare recipient continues using stale permissions after authorization record is updated in Production CloudKit
I am developing an iOS/iPadOS app using SwiftUI, SwiftData, CloudKit, and CKShare. I need help determining why an already-approved CKShare recipient is not receiving updated application-level authorization. Architecture The owner stores working data locally in SwiftData and explicitly mirrors shared data into a custom CloudKit zone named AthleteVaultSharedSchoolData. The owner writes these records to privateCloudDatabase. Recipients accept a zone-wide CKShare and read the accepted zone through sharedCloudDatabase. Each approved recipient also has an AVSchoolMembershipAuthorization record in that shared zone. Its deterministic record name is based on the recipient's CloudKit user record ID: AVSchoolMembershipAuthorization- The authorization contains the recipient's role and arrays of permitted team, sport, and player UUIDs. What works The recipient successfully accepted the share and can download the shared school data. The recipient has previously fetched his authorization from the accepted shared zone and received the correct initial permissions. The owner can change that recipient's permissions and save the updated authorization. I verified in CloudKit Console → Production → Private Database that there is exactly one authorization record for this recipient. It is active and contains the newly selected playerIDs. The record's updatedAt also changes when the administrator saves the permissions. Both owner and recipient are testing the same TestFlight Production build. The problem After changing an already-approved recipient's permissions, the Production authorization record is correct, but the recipient continues operating with the previous player permissions after closing and reopening the app. For example, the administrator removes Player A and grants Player B. CloudKit Console shows the authorization now contains Player B instead of Player A, but the recipient continues seeing Player A and does not see Player B. On the recipient I obtain the current CloudKit user record ID, locate the accepted shared zone, construct the deterministic authorization record ID, and fetch it from the shared database: let recordID = CKRecord.ID( recordName: "AVSchoolMembershipAuthorization-(userRecordID.recordName)", zoneID: acceptedZoneID ) container.sharedCloudDatabase.fetch(withRecordID: recordID) { record, error in // decode current authorization } Once the authorization is returned, the app explicitly reconciles its local SwiftData permission rows: permissions absent from the current authorization are deleted and newly granted permissions are inserted. Production schema During troubleshooting I discovered that AVSchoolMembershipAuthorization had initially existed only in Development. That schema has now been deployed to Production. Before deployment, Production correctly returned a “Cannot create new type AVSchoolMembershipAuthorization in production schema” error. After deploying the schema, the owner save succeeds and the updated authorization is visible directly in the Production CloudKit Console. Therefore the current problem occurs after the Production authorization has been successfully saved. Questions With a zone-wide CKShare, should records created or modified in the owner's shared custom zone automatically become visible to an already-accepted participant through sharedCloudDatabase? If AVSchoolMembershipAuthorization was created after the recipient originally accepted the zone-wide share, is any additional operation required to expose that record to the existing participant? Is sharedCloudDatabase.fetch(withRecordID:), using the accepted shared-zone ID and exact deterministic record ID, the appropriate way to retrieve the latest server version? Can an accepted participant continue receiving an older version of a record after the owner successfully saves a newer version to the Production private database? If so, what API or synchronization pattern should be used to reliably obtain the current version? When changing CKShare.Participant.permission for an existing participant at the same time as changing application-level authorization in a custom CKRecord, is there another CKShare operation required? Is a per-recipient authorization CKRecord inside a zone-wide shared zone an appropriate CloudKit design, or is there a recommended pattern for per-recipient authorization? I can provide the relevant CloudKit service code, CloudKit Console screenshots, and additional diagnostics if needed. Thank you for any guidance on the expected CloudKit behavior for updated records in an already-accepted zone-wide CKShare.
Replies
0
Boosts
0
Views
185
Activity
4w
NSPersistentCloudKitContainer export permanently blocked: RecordDelete fails with BAD_REQUEST on _pcs_data, even after fresh install
Our SwiftData app (NSPersistentCloudKitContainer under the hood, Production environment, iOS 27.0, private database, default zone com.apple.coredata.cloudkit.zone, no sharing) can no longer export for one user account. On every launch, the first export is a RecordDelete of duplicate records (CD_HealthMetricsSnapshot / CD_DailyLog) that our deduplication removed locally. The CloudKit Console shows it failing with overallStatus: USER_ERROR, error: BAD_REQUEST, returnedRecordTypes: "_pcs_data". On device it surfaces as CKErrorDomain Code=2 "CKInternalErrorDomain: 1011" (partialFailure). After that, NSCloudKitMirroringDelegate reports "Never successfully initialized" and no further export happens in that process. Imports still succeed. It reproduces after deleting and reinstalling the app. On a fresh install, the initial import succeeds, and the very first export, deleting records that were only downloaded and never modified locally, fails the same way. Earlier delete batches from the same deduplication on the same account succeeded, so it seems tied to specific records or the zone's PCS state. Request IDs: E49E4252-99A6-4103-8C03-1D0738005AA3, 4BA5133D-A1F5-423F-BDE6-F65B76B66375, E8D27548-BED1-49A4-9214-3C1A35CDC8C7. Container: iCloud.com.backbonesvc.fastsignal.ios. Questions: What causes a RecordDelete to fail with BAD_REQUEST on _pcs_data? Is there a supported way to clear this without purging the zone? purgeObjectsAndRecordsInZone is documented to also delete local objects, which we must avoid. Can Apple inspect or repair the server-side state for these request IDs?
Replies
0
Boosts
0
Views
172
Activity
4w
Which technology should be used to save configuration information?
I want to save some configure information for my app. Which technology should be used to save configuration information? SwiftData or a json file? I'm not sure whether it's appropriate to use SwiftData.It seems that SwiftData is suitable for saving multiple data of the same type, such as saving multiple student information. If I use SwiftData to save a configuration information, there may be the following code in the place where it is used: @query private var configs:[ConfigInfo] … name = configs[0].name If there are other ways to implement it, please let me know. Thanks.
Replies
1
Boosts
0
Views
337
Activity
Sep ’26
CloudKit Production sync fails with CKInternalErrorDomain 1011 and BAD_REQUEST on _pcs_data
Hi, I’m seeing a CloudKit Production sync failure in an iOS app using SwiftData/Core Data with private CloudKit mirroring. Sync worked correctly after release, then stopped working without any new app build being released. Device logs show: CKInternalErrorDomain Code=1011 and Core Data reports that CloudKit mirroring was never successfully initialized. CloudKit Production logs also show a native PRIVATE database request failing with: USER_ERROR / BAD_REQUEST involving the internal record type: _pcs_data The Production schema, private zone, and subscription are still present. I have not reset Production or deleted any zones/subscriptions. I have already filed a Feedback Assistant report with diagnostics. Has anyone seen this pattern before? Is there a safe developer-side remediation, or is this typically an Apple-side CloudKit/PCS issue? I want to avoid any destructive action that could risk existing user data.
Replies
2
Boosts
0
Views
531
Activity
Sep ’26
SwiftData with CloudKit Error: Error updating background task request
Hi, Overview I have a SwiftData project which automatically syncs with CloudKit. When I run the app, I see the following error in Xcode logs. Error updating background task request: Error Domain=BGSystemTaskSchedulerErrorDomain Code=3 "(null)" My attempt I can enable Background processing (under Signing & Capabilities > Background modes), but I don't know the BGTaskSchedulerPermittedIdentifiers to add in the Info.plist Questions How can I resolve this? If I should enable background processing, what are the BGTaskSchedulerPermittedIdentifiers to add in Info.plist?
Replies
19
Boosts
0
Views
2.6k
Activity
Sep ’26
SwiftData predicate with optional chaining failing on OS 27
The following predicate (which returns results on OS 26) only returns results on OS 27 when I comment out the last line: reviewDescriptor = FetchDescriptor<Flashcard>( predicate: #Predicate { $0.sourceLanguageRaw == rawLang && $0.cardStateRaw == reviewRaw && $0.dueDate < currentDate && !$0.isSuspended && advancedStudyEnabled.evaluate($0) && !($0.promotionLog?.isProcessing ?? false) // <- here }, sortBy: [SortDescriptor(\.previousInterval)] ) // where Flashcard — PromotionLog is a one-to-one optional relationship Because I’m still getting results on OS 26 from the same data, my guess is the line with optional chaining somehow causes the entire predicate to fail silently, without crashing the app. But I also don’t see any posts about it, so maybe it’s something I’m doing wrong? Is anyone else experiencing this? Any workarounds? ETA: However, this chaining appears to be working just fine: reviewDescriptor.predicate = #Predicate<Flashcard> { $0.sourceLanguageRaw == rawLang && $0.cardStateRaw == reviewRaw && ($0.pronunciationLog?.dueDate ?? currentDate) < currentDate && $0.pronunciationLog?.practiceStateRaw != masteredRaw && !$0.isSuspended } So I’m a bit lost. Maybe the syntax of the first? Something about using it alongside .evaluate()? ETA2: After a bit more debugging, when && !($0.promotionLog?.isProcessing ?? false) is commented out, a Flashcard where promotionLog == nil shows up. But if promotionLog == nil, the line should evaluate to !(false), i.e. true. So why would that line stop the card from showing up in the first place?
Replies
1
Boosts
0
Views
286
Activity
Sep ’26
ShieldConfigurationExtension & SwiftData
Hi, I am developing a Screen Time App and I am having issues with the ShieldConfigurationExtension (ShieldConfigurationDataSource). I know this extensions is sandboxed but I should be able to read data from the main app. I am using SwiftData as my database, but I am unable to initialize it in the extensions with an error indicating insufficient file permissions. I have App Group set up and I am able to share data using UserDefaults but that is just inconvenient. Is there any way I could just open the SwiftData in read only mode so that I could display the user some info on the shield? SwiftData Init: private func setupContainer() throws { let schema = Schema([ DogEntity.self, HouseEntity.self ]) // Use app group container if available let config: ModelConfiguration if let containerURL = FileManager.default.containerURL( forSecurityApplicationGroupIdentifier: "group.\(Bundle.app.bundleIdentifier ?? "")" ) { config = ModelConfiguration(schema: schema, url: containerURL.appendingPathComponent("default.sqlite")) } else { config = ModelConfiguration(schema: schema) } self.container = try ModelContainer(for: schema, configurations: [config]) } Error in extension: fault: Attempt to add read-only file at path file:///private/var/mobile/Containers/Shared/AppGroup/51431199-5919-4AE6-940C-6FE3C53EEB46/default.sqlite read/write. Adding it read-only instead. This will be a hard error in the future; you must specify the NSReadOnlyPersistentStoreOption. error: (3) access permission denied error: Encountered exception error during prepareSQL for SQL string 'SELECT TBL_NAME FROM SQLITE_MASTER WHERE TBL_NAME = 'Z_METADATA'' : access permission denied with userInfo { NSFilePath = "/private/var/mobile/Containers/Shared/AppGroup/51431199-5919-4AE6-940C-6FE3C53EEB46/default.sqlite"; NSSQLiteErrorDomain = 3; } while checking table name from store: <NSSQLiteConnection: 0x154100300> error: Store failed to load. <NSPersistentStoreDescription: 0x15402d590> (type: SQLite, url: file:///private/var/mobile/Containers/Shared/AppGroup/51431199-5919-4AE6-940C-6FE3C53EEB46/default.sqlite) with error = Error Domain=NSCocoaErrorDomain Code=256 "The file “default.sqlite” couldn’t be opened." UserInfo={NSFilePath=/private/var/mobile/Containers/Shared/AppGroup/51431199-5919-4AE6-940C-6FE3C53EEB46/default.sqlite, NSSQLiteErrorDomain=3} with userInfo { NSFilePath = "/private/var/mobile/Containers/Shared/AppGroup/51431199-5919-4AE6-940C-6FE3C53EEB46/default.sqlite"; NSSQLiteErrorDomain = 3; } Any help appreciated 🙂
Replies
2
Boosts
0
Views
390
Activity
Sep ’26
HistoryObserver eventCounter updating 9-16 times per app launch because of CloudKit syncing?
I created a finance tracking app. I wanted to use HistoryObserver to determine when Transactions are created/updated/deleted on another device with the same appleId, so I can update some charts I have an @Observable model that has this (simplified) setup: private(set) var transactionObserver: HistoryObserver? func setupHistoryObserver(modelContainer: ModelContainer) throws { transactionObserver = try HistoryObserver( observedModels: [Transaction.self], modelContainer: modelContainer, ) } var transactionUpdateTrigger: Int { transactionObserver?.eventCounter ?? 0 } I have the view setup with: .task(id: viewModel.transactionUpdateTrigger) { print("updating chart data: \(viewModel.transactionUpdateTrigger)") await updateChartData() } When I launch my app on my iPhone, I see: updating chart data: 0 updating chart data: 1 updating chart data: 2 updating chart data: 3 updating chart data: 4 updating chart data: 5 updating chart data: 6 updating chart data: 7 updating chart data: 8 updating chart data: 9 updating chart data: 10 On simulator, it only fires once: updating chart data: 0 The docs state: "When relevant changes are detected, the observer updates its eventCounter property." The happens every single time I try deploying my app to my iPhone on iOS 27 beta 8, but with varying numbers of eventCounter increments. I only have the app installed on a single device with my Apple Account. Why is this happening? There should be no changes to my models, as is clear because there's no issues when running this in simulator.
Replies
2
Boosts
0
Views
621
Activity
Sep ’26
#Predicate needs better validation
Hi, Overview I am finding #Predicate to be a bit tricky when used with Swift Data It compiles fine but crashes at runtime I know the fix for the problem just wondering if such pitfalls can be avoided at compile time Exception *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'can't use NULL on left hand side' terminating due to uncaught exception of type NSException CoreData: error: SQLCore dispatchRequest: exception handling request: <NSSQLFetchRequestContext: 0x11209b000> , can't use NULL on left hand side with userInfo of (null) Questions Could anything be done to improve the safety to avoid such issues at runtime? Could I write the code better (better than the fix below) to avoid this? My thoughts Fix is possible however it wasn't obvious to me that there was a problem with my original code Would be nice to prevent them at compile time if possible. Currently got to be really careful to avoid such crashes. Code import Foundation import SwiftData @Model class Car { var name: String var modelRawValue: String? init(name: String, modelRawValue: String?) { self.name = name self.modelRawValue = modelRawValue } } enum CarModel: String, CaseIterable { case modelA case modelB } func makePredicate(filterModels: [CarModel]?) -> Predicate<Car> { let filterRawValues = filterModels?.map { $0.rawValue } let predicate = #Predicate<Car> { car in if let filterRawValues { if let carModelRawValue = car.modelRawValue { filterRawValues.contains(carModelRawValue) } else { false } } else { true } } return predicate } func fetch(context: ModelContext) throws { let predicate = makePredicate(filterModels: nil) let fetchDescriptor = FetchDescriptor(predicate: predicate) do { let cars = try context.fetch(fetchDescriptor) print(cars.count) } catch { print("Error: \(error)") throw error } } Fix func makePredicate(filterModels: [CarModel]?) -> Predicate<Car> { // Checking nil condition even before creating the predicate fixes the issue guard let filterModels else { return .true } let filterRawValues = filterModels.map { $0.rawValue } let predicate = #Predicate<Car> { car in if let carModelRawValue = car.modelRawValue { filterRawValues.contains(carModelRawValue) } else { false } } return predicate }
Replies
3
Boosts
0
Views
706
Activity
Sep ’26
Migrating a Transformable attribute from CoreData to SwiftData
I am migrating a CloudKit-synchronized multi-platform app from CoreData to SwiftData. (Xcode 27.0 beta 5). One of my Models/Entities contains a Transformable attribute, which is defined in the CoreData model editor as: and which is defined in the generated CoreData class as @NSManaged nonisolated public var authorNames: [String]? Using the built-in translation took, Xcode created a Model wich included @Attribute(.transformable(by: "NSSecureUnarchiveFromDataTransformerName")) var authorNames: [String] = [] This compiles but does not run. In the function func getModelContainer() throws -> ModelContainer { let storeURL = try FileManager.default.url( for: .applicationSupportDirectory, in: .userDomainMask, appropriateFor: nil, create: true) .appendingPathComponent(dbName) let modelConfiguration = ModelConfiguration( schema: dbSchema, url: storeURL, cloudKitDatabase: .automatic) let container = try ModelContainer( for: dbSchema, migrationPlan: MigrationPlan.self, configurations: [modelConfiguration]) return container } the app throws a fatal error in the ModelContainer initializer, SwiftData/SchemaCoreData.swift:398: Fatal error: Application must register a ValueTransformer for NSSecureUnarchiveFromDataTransformerName So I added the following line of code at the top of this function: ValueTransformer.setValueTransformer( NSSecureUnarchiveFromDataTransformer(), forName: .secureUnarchiveFromDataTransformerName) which also compiles but also throws the same fatal error in the same place. Can anyone suggest how to resolve this problem? This is a CloudKit synchronized app, so I am constrained in what I can do with this attribute.
Replies
1
Boosts
0
Views
309
Activity
Aug ’26
Issue with SwiftData migration and renaming property when using @Attribute(originalName:)
Put simply, @Attribute(originalName:) doesn't seem to work. I'm getting "Validation error missing attribute values on mandatory destination relationship". Tried with Xcode 26.6 on iOSes 18.6 and 26.5, and with Xcode 27 on iOS27. Same result. Original Schema: typealias CurrentSchemaModel = SchemaV100 typealias House = CurrentSchemaModel.House typealias Automobile = CurrentSchemaModel.Automobile enum SchemaV100: VersionedSchema { static let versionIdentifier: Schema.Version = .init(1, 0, 0) static var models: [any PersistentModel.Type] { [Automobile.self, House.self] } @Model final class Automobile { var id: UUID = UUID() var name: String = "" init(name: String) { self.name = name } } @Model final class House { var id: UUID = UUID() var name: String = "" var automobile: Automobile var createdDate: Date = Date() init(name: String, automobile: Automobile) { self.name = name self.automobile = automobile } } } Updated Schema (renamed House.automobile to House.automobileOne): typealias CurrentSchemaModel = SchemaV101 /*updated from SchemaV100 */ enum SchemaV101: VersionedSchema { static let versionIdentifier: Schema.Version = .init(1, 0, 1) static var models: [any PersistentModel.Type] { [Automobile.self, House.self] } @Model final class Automobile { var id: UUID = UUID() var name: String = "" init(name: String) { self.name = name } } @Model final class House { var id: UUID = UUID() var name: String = "" @Attribute(originalName: "automobile") var automobileOne: Automobile var createdDate: Date = Date() init(name: String, automobileOne: Automobile) { self.name = name self.automobileOne = automobileOne } } } Migration Plan: enum TestRenameMigrationPlan: SchemaMigrationPlan { static var schemas: [any VersionedSchema.Type] { let currentSchemas: [any VersionedSchema.Type] = [SchemaV100.self, SchemaV101.self] return currentSchemas } static var stages: [MigrationStage] { [migrateV100toV101] } // MARK: - V101 static let migrateV100toV101 = MigrationStage.lightweight(fromVersion: SchemaV100.self, toVersion: SchemaV101.self) } SQLDebug logging shows this: CoreData: sql: ALTER TABLE ZHOUSE RENAME TO _T_ZHOUSE CoreData: sql: CREATE TABLE ZHOUSE ( Z_PK INTEGER PRIMARY KEY, Z_ENT INTEGER, Z_OPT INTEGER, ZAUTOMOBILEONE INTEGER, ZCREATEDDATE TIMESTAMP, ZNAME VARCHAR, ZID BLOB ) CoreData: sql: INSERT INTO ZHOUSE (Z_PK,Z_ENT,Z_OPT,ZAUTOMOBILEONE,ZCREATEDDATE,ZNAME,ZID) SELECT Z_PK,Z_ENT,Z_OPT,?,ZCREATEDDATE,ZNAME,ZID FROM _T_ZHOUSE CoreData: details: SQLite bind[0] = nil Seems excessive to recreate table for a simple column rename, but I digress... The curious part is the binding, SQLite bind[0] = nil, where I'd expect the originalName value (e.g. ZAUTOMOBILE) to be used. Any thoughts or explanations would be appreciated. Steve
Replies
0
Boosts
0
Views
84
Activity
Aug ’26
How do I write this #Predicate?
I have two Models which are defined (simplified) as follows: @Model final class Book { var id: UUID = UUID() var title: String = "" var authors: [Author]? = [] } @Model final class Author { var id: UUID = UUID() var name: String "" @Relationship(inverse: \Book.authors) var books: [Book]? = [] } Both Book.authors and Author.books are defined as optionals to satisfy the requirements of CloudKit, although it is clear from the above that neither is ever actually nil. I am trying to write a #Predicate that finds objects of type Book with a title that matches a specified title and with an author that matches a specified author. The function I'd like to write looks something like this: func find(title: String, author: Author, with context: ModelContext) -> Book? { let same = ComparisonResult.orderedSame let predicate = #Predicate<Book> { book in book.title.caseInsensitiveCompare(title) == same && book.authors!.contains(where: { $0.id == author.id }) } let descriptor = FetchDescriptor<Book>(predicate: predicate) return try? context.fetch(descriptor).first } This function fails to compile inside the expansion of the #Predicate macro with a very long error message: Cannot convert value of type (a long 'PredicateExpresions....') (aka (another log 'PredicateExpressions....')) to closure result type 'any StandardPredicateExpression<Bool>' I don't understand. How can I write this predicate so that it will both compile and work? I know how to work around this problem, but would like to both deepen my understanding of Swift and SwiftData and to avoid the (inelegant) workaround.
Replies
2
Boosts
0
Views
506
Activity
Aug ’26
Sandboxed macOS app using SwiftData and CloudKit cannot initialize CloudKit mirroring.
I have a Mac and iOS app intended to sync data in iCloud. Both apps in TestFlight, the iOS reads and writes to iCloud but the Mac fails as the App Sandbox denies mach-lookup com.apple.cloudd, so NSCloudKitMirroringDelegate` never reaches the daemon and setup fails permanently. I have a minimal app reproducing the issue on for the Mac app. I also submitted a feedback FB24450529
Replies
1
Boosts
0
Views
754
Activity
Aug ’26