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
Sort by:

Post

Replies

Boosts

Views

Activity

SwiftUI view is not updated properly
Task: A child view should show depending on a boolean flag the corresponding view. The flag is calculated from a model which is given by parent view. Problem: The flag is false in init, which is correct. However in body it's true, which is incorrect. Why value in body isn't consistent to init? Is there a race condition? The child view's is rendered thrice, that's another issue, but flag is in init and body as described before. Parent view looks like this: struct ParentView: View { private var groupedItems: [GroupedItems] = [] init(items: [Item]) { Dictionary(grouping: items) { $0.category.name } .forEach { let groupedItems = GroupedItems(categoryName: $0.key, items: $0.value) self.groupedItems.append(groupedItems) } } var body: some View { ChildView(groupedItems) } } Child view looks like this: struct ChildView: View { @State private var showItems: Bool init(_ groupedItems: GroupedItems) { self._showItems = State(initialValue: !groupedItems.completed) } var body: some View { if showItems { AView() } else { BView() } } } Model looks like this: @Model final class Item: Identifiable { @Attribute(.unique) public var id: String public var name: String public var completed = false } struct GroupedItems { var categoryName: String var items: [Item] var completed: Bool { items.filter { !$0.completed }.isEmpty } }
3
0
212
1w
Questions About CloudKit Security Roles and Permissions
Hi, I'm using CloudKit to create an app that backs up and records your data to iCloud. Here's what I'm unsure about: I understand that the 'CloudKit Dashboard' has 'Security Roles'. I thought these were meant to set permissions for accessing and modifying users' data, but I found there was no change even when I removed all 'Permissions' from 'Default Roles'. Can you clarify? I'd like to know what _world, _icloud, and _creator in Default Roles mean respectively. I would like to know what changes the creation, read, and write permissions make. Is it better to just use the default settings? Here's what I understand so far: Default Roles: _world: I don't know _icloud: An account that is not my device but is linked to my iCloud _creator: My Device Permissions: create: Create data read: Read data write: Update and delete data. I'm not sure if I understand this correctly. Please explain.
1
0
199
1w
Online data to swift UI
Hello! I have been working on an app for quite some time now, and one of my views is of a bunch of different articles that my brand has written. The articles can be found on their website, and so as of late, I have just been copying and pasting all of the data from each article into a JSON file in my app; However, as the list of articles grow, I need to fetch the data directly from the website and have it integrated with my code, so every time a new article is published, users dont have to update their app. Is there any way someone could help with this? I've been struggling for a while now. Thanks!
2
0
179
1w
SwiftData error on IOS18, Never access a full future backing data
try to update my app from iOS 17 to io 18, I'm using SwiftData to save the data on the memory, on iOS 17 all works fine but I tried to export my app to iOS 18 and I get a strange error when I try to delate a playlist from SwiftData memory. Thread 10: Fatal error: Never access a full future backing data - PersistentIdentifier(id: SwiftData.PersistentIdentifier.ID(url: x-coredata://4885953A-BDB2-4CD1-9299-B2FBBB899EB7/PlaylistItem/p372), implementation: SwiftData.PersistentIdentifierImplementation) with Optional(B2A80504-2FE1-4C86-8341-3DDE8B6AB913) the code where this error happen is very simple, func deletePlaylist(_ playlist: PlayListModel) async throws { print("attempt to delate :, \(playlist.playlistName)") context.delete(playlist) try context.save() // error here on the save } Error only happen on iOS 18 not on the 17.
3
5
255
1w
SwiftData custom migration crash
Starting point I have an app that is in production that has a single entity called CDShift. This is the class: @Model final class CDShift { var identifier: UUID = UUID() var date: Date = Date() ... } This is how this model is written in the current version. Where I need to go Now, I'm updating the app and I have to do some modifications, that are: add a new entity, called DayPlan add the relationship between DayPlan and CDShift What I did is this: enum SchemaV1: VersionedSchema { static var versionIdentifier = Schema.Version(1, 0, 0) static var models: [any PersistentModel.Type] { [CDShift.self] } @Model final class CDShift { var identifier: UUID = UUID() var date: Date = Date() } } To encapsulate the current CDShift in a version 1 of the schema. Then I created the version 2: enum SchemaV2: VersionedSchema { static var versionIdentifier = Schema.Version(2, 0, 0) static var models: [any PersistentModel.Type] { [CDShift.self, DayPlan.self] } @Model final class DayPlan { var identifier: UUID = UUID() var date: Date = Date() @Relationship(inverse: \CDShift.dayPlan) var shifts: [CDShift]? = [] } @Model final class CDShift { var identifier: UUID = UUID() var date: Date = Date() var dayPlan: DayPlan? = nil } } The migration plan Finally, I created the migration plan: enum MigrationPlan: SchemaMigrationPlan { static var schemas: [any VersionedSchema.Type] { [SchemaV1.self, SchemaV2.self] } static let migrateV1toV2 = MigrationStage.custom( fromVersion: SchemaV1.self, toVersion: SchemaV2.self) { context in // willMigrate, only access to old models } didMigrate: { context in // didMigrate, only access to new models let shifts = try context.fetch(FetchDescriptor<SchemaV2.CDShift>()) for shift in shifts { let dayPlan = DayPlan(date: shift.date) dayPlan.shifts?.append(shift) context.insert(dayPlan) } } static var stages: [MigrationStage] { print("MigrationPlan | stages called") return [migrateV1toV2] } } The ModelContainer Last, but not least, how the model container is created in the App: struct MyApp: App { private let container: ModelContainer init() { container = ModelContainer.appContainer } var body: some Scene { WindowGroup { ... } .modelContainer(container) } } This is the extension of ModelContainer: extension ModelContainer { static var appContainer: ModelContainer { let schema = Schema([ CDShift.self, DayPlan.self ]) let modelConfiguration = ModelConfiguration( schema: schema, isStoredInMemoryOnly: Ecosystem.current.isPreview, groupContainer: .identifier(Ecosystem.current.appGroupIdentifier) ) do { // let container = try ModelContainer(for: schema, configurations: modelConfiguration) let container = try ModelContainer(for: schema, migrationPlan: MigrationPlan.self, configurations: modelConfiguration) AMLogger.verbose("SwiftData path: \(modelConfiguration.url.path)") return container } catch (let error) { fatalError("Could not create ModelContainer: \(error)") } } } The error This has always worked perfectly until the migration. It crashes on the fatalError line, this is the error: Unable to find a configuration named 'default' in the specified managed object model. Notes It seems that the version of the store is never updated to 2, but it keeps staying on 1. I tried also using the lightweight migration, no crash, it seems it recognizes the new entity, but the store version is always 1. iCloud is enabled I thought that the context used in the custom migration blocks is not the "right" one that I use when I create my container If I use the lightweight migration, everything seems to work fine, but I have to manually do the association between the DayPlan and the CDShift objects Do you have an idea on how to help in this case?
7
0
326
7m
Saving SwiftData in Background Does Not Update @Query
I'm trying to use SwiftData for a new app after ~20 years of Core Data (and EOF before that). So while I'm new to SwiftData, I'm not new to Apple persistence frameworks. I've got a pretty typical workflow - need to load some JSON from the network, convert that into model objects. I've created an actor using the @ModelActor macro and I'm using that to do the network fetch and insert. I can set breakpoints in this code and see that it does indeed run and it's running on a non-main queue. That all seems fine. The problem is that my @Query powered variable in my SwiftUI user interface does not get updated when this data is loaded and saved as I would expect it to. I'm passing in the container to the actor using modelContext.container from the same modelContext that is powering the view / in the environment. My understanding was that like Core Data before it, the SwiftData framework was listening for the relevant notifications passed by the container/context, processing those and updating the UI but I can only see my data if I quit and relaunch the app. This seems like it should be a very common use case but I've not found much online. Not sure if that means I'm just doing something fundamentally wrong or what. Tested on both iOS 18 and 17 with the same results. Anyone else doing this successfully? What could I be doing wrong?
1
4
269
2w
Issue with observing SwiftData model and UndoManager
I have created a minimum example to demonstrate an issue with observing SwiftData model and UndoManager. This project includes a simple NavigationSplitView, an Item SwiftData model that is being persisted and an enabled UndoManager. Problem: The SwiftData model Item can be observed as expected. Changing the date in the DetailView works as expected and all related views (ListElementView + DetailView) are updated as expected. When pressing ⌘+Z to undo with the enabled UndoManager, deletions or inserts in the sidebar are visible immediately (and properly observed by ContentView). However, when changing the timestamp and pressing ⌘+Z to undo that change, it is not properly observed and immediately updated in the related views (ListElementView + DetailView). Further comments: Undo operation to the model value changes (here: timestamp) are visible in the DetailView when changing sidebar selections Undo operation to the model value changes (here: timestamp) are visible in the ListElementView when restarting the app Undo operation to the model value changes (here: timestamp) are are properly observed and immediately visible in the sidebar, when ommiting the ListElementView (no view encapsulation) Relevant code base: struct ContentView: View { @Environment(\.modelContext) private var modelContext @Query private var items: [Item] @State private var selectedItems: Set<Item> = [] var body: some View { NavigationSplitView { List(selection: $selectedItems) { ForEach(items) { item in ListElementView(item: item) .tag(item) } .onDelete(perform: deleteItems) } .navigationSplitViewColumnWidth(min: 180, ideal: 200) .toolbar { ToolbarItem { Button(action: addItem) { Label("Add Item", systemImage: "plus") } } } } detail: { if let item = selectedItems.first { DetailView(item: item) } else { Text("Select an item") } } .onDeleteCommand { deleteSelectedItems() } } private func addItem() { withAnimation { let newItem = Item(timestamp: Date()) modelContext.insert(newItem) } } private func deleteItems(offsets: IndexSet) { withAnimation { for index in offsets { modelContext.delete(items[index]) } } } private func deleteSelectedItems() { for selectedItem in selectedItems { modelContext.delete(selectedItem) selectedItems.remove(selectedItem) } } } struct ListElementView: View { @Bindable var item: Item var body: some View { Text("Item at \(item.timestamp, format: Date.FormatStyle(date: .numeric, time: .standard))") } } struct DetailView: View { @Bindable var item: Item var body: some View { Text(item.timestamp, format: Date.FormatStyle(date: .numeric, time: .standard)) DatePicker(selection: $item.timestamp, label: { Text("Change Date:") }) } } @Model final class Item { var timestamp: Date init(timestamp: Date) { self.timestamp = timestamp } } It seems that the UndoManager does not trigger a redraw of the ContentView through the items query? Is this a bug or a feature?
0
0
134
2w
SampleTrips Previews work, but not in my primary project.
I wanted to get my SwiftData previews working in my primary project, so I started modeling them after the SampleTrips project. After messing around with that & being unable to make it work, I brought the same (working) sample code into my main project, unfortunately that's not working... I've attached the preview error (note, there's nothing in the Diagnostic Reports). //Sample code that works in it's own project, but not my primary target. import SwiftUI import SwiftData struct TestSwiftDataStuffView: View { let trip: Trip var body: some View { VStack { Image(systemName: "globe") .imageScale(.large) .foregroundStyle(.tint) Text("Hello, \(trip.name)!") .padding() .foregroundColor(.red) } .padding() } } #Preview(traits: .sampleDataSecondary) { @Previewable @Query var trips: [Trip] TestSwiftDataStuffView(trip: trips.first!) } actor DataModelSecondary { struct TransactionAuthor { static let widget = "widget" } static let shared = DataModelSecondary() private init() {} nonisolated lazy var modelContainer: ModelContainer = { let modelContainer: ModelContainer let schema = Schema([ Trip.self ]) do { let modelConfiguration = ModelConfiguration(schema: schema, isStoredInMemoryOnly: false, cloudKitDatabase: .none) modelContainer = try ModelContainer(for: schema, configurations: [modelConfiguration]) } catch { fatalError("Failed to create the model container: \(error)") } return modelContainer }() } @Model class Trip { @Attribute(.preserveValueOnDeletion) var name: String init(name: String) { self.name = name } } extension Trip { static var previewTrips: [Trip] { [ Trip(name: "Revenant"), Trip(name: "Newcastle"), Trip(name: "Bianca") ] } } struct SampleDataSecondary: PreviewModifier { static func makeSharedContext() throws -> ModelContainer { let config = ModelConfiguration(isStoredInMemoryOnly: true) let container = try ModelContainer( for: Trip.self, configurations: config ) SampleDataSecondary.createSampleData(into: container.mainContext) return container } func body(content: Content, context: ModelContainer) -> some View { content.modelContainer(context) } static func createSampleData(into modelContext: ModelContext) { Task { @MainActor in let sampleDataTrips: [Trip] = Trip.previewTrips let sampleData: [any PersistentModel] = sampleDataTrips //+ sampleDataLA + sampleDataBLT sampleData.forEach { modelContext.insert($0) } try? modelContext.save() } } } @available(iOS 18.0, *) extension PreviewTrait where T == Preview.ViewTraits { @MainActor static var sampleDataSecondary: Self = .modifier(SampleDataSecondary()) } Xcode16Preview.txt
3
0
381
2w
SwiftUI State not reliable updating
Hello, I have a SwiftUI view with the following state variable: @State private var startDate: Date = Date() @State private var endDate: Date = Date() @State private var client: Client? = nil @State private var project: Project? = nil @State private var service: Service? = nil @State private var billable: Bool = false Client, Project, and Service are all SwiftData models. I have some view content that binds to these values, including Pickers for the client/project/service and a DatePicker for the Dates. I have an onAppear listener: .onAppear { switch state.mode { case .editing(let tt): Task { await MainActor.run { startDate = tt.startDate endDate = tt.endDate client = tt.client project = tt.project service = tt.service billable = tt.billable } } default: return } } This works as expected. However, if I remove the Task & MainActor.run, the values do not fully update. The DatePickers show the current date, the Pickers show a new value but tapping on them shows a nil default value. What is also extremely strange is that if tt.billable is true, then the view does update as expected. I am using Xcode 15.4 on iOS simulator 17.5. Any help would be appreciated.
0
0
182
2w
How to properly add data files into a SwiftData ModelDocument file package
Hi all, I am working on a macOS/iOS sandboxed app with SwiftUI/SwiftData. The app saves its' data into a ModelDocument file. But I want to also save large binary data files into this file. I create the DocumentGroup scene with: DocumentGroup(editing: Entry.self, contentType: .myDocument) { MainWindowView() } In my MainWindowView, I use @Environment(\.documentConfiguration) private var documentConfiguration to get the URL to the user created ModelDocument file URL. When I need to add large binary file into the ModelDocument file, I call a method in my model: func saveReferencedData(_ data: Data, documentURL: URL?) throws { let logger = Logger(subsystem: "saveReferencedData", category: "Asset") if let documentURL { let referencedFileName = "\(entryIdentifier)_\(assetIdentifier).\(assetType)" let tempFileURL = documentURL.appending(components: referencedFileName) if documentURL.startAccessingSecurityScopedResource() { do { try data.write(to: tempFileURL, options: []) } catch { documentURL.stopAccessingSecurityScopedResource() throw AssetFileOperationError.unableToSaveReferenceFile } self.referencedFileLocation = referencedFileName logger.debug("Successfully saved image data to: \(referenceFileURL)") } documentURL.stopAccessingSecurityScopedResource() } else { logger.debug("ERROR! Unable to save referenced image file because document URL is nil.") } } When this method is called, the data file is saved, but immediately I gets this diablog box: If I click on any of the options in the dialog box, the binary data file is removed. I think this is a permission problem and I am not writing to the ModelDocument file correctly. But I can not find any information online to experiment more. Does anyone have experience with a customized ModelDocument file with more data files written into it? Or if you have any insight or advice, it would be greatly appreciated. Thank you so much for reading.
2
1
164
6d
When to use structs with swift data?
I am unsure the correct way to model my data. I have a swift data object and then some referenced objects. Is there ever a reason those should just be structs or should they always be swift data objects themselves? for example right now this is what I'm doing: @Model final class Exam { var timestamp: Date @Attribute(.unique) var examID: UUID var title: String var questions: [Question] ... } and Question is struct Question: Codable, Identifiable { var id: UUID var number: Int var points: Int var prompt: String var answer: String } is there any problem with this or should I not be using a Struct for Question and instead use another Swift Data object with @Relationship ? I thought since its a simple object just using a struct would be fine, however... when I create a new Question object, it seems to create SwiftUI retain cycles with the warning === AttributeGraph: cycle detected through attribute 633984 === in the terminal for example, Button("Add Question", systemImage: "questionmark.diamond") { let newQuestion = Question(id: UUID(), number: exam.questions.count+1, points: 1, prompt: "", answer: "", type: .multipleChoice) exam.questions.append(newQuestion) } So, is it ok to mix structs with swift data objects or is it not best practice? And is this causing the SwiftUI retain cycles or are the issues unrelated?
1
0
187
2w
Tokenised text search in SwiftData help
The SwiftData predicate documentation says that it supports the contains(where:) sequence operation in addition to the contains(_:) string comparison but when I put them together in a predicate to try and perform a tokenised search I get a runtime error. Unsupported subquery collection expression type (NSInvalidArgumentException) I need to be able to search for items that contain at least one of the search tokens, this functionality is critical to my app. Any suggestions are appreciated. Also does anyone with experience with CoreData know if this is possible to do in CoreData with NSPredicate? import SwiftData @Model final class Item { var textString: String = "" init() {} } func search(tokens: Set<String>, context: ModelContext) throws -> [Item] { let predicate: Predicate<Item> = #Predicate { item in tokens.contains { token in item.textString.contains(token) } } let descriptor = FetchDescriptor(predicate: predicate) return try context.fetch(descriptor) }
2
1
306
2w
Crash by SwiftData MigarionPlan
I am a develop beginner. Recently, my App used SwiftData's MigraitonPlan, which caused it to crash when I opened it for the first time after updating in TestFlight or the store. After clicking it a second time, I could enter the App normally, and I could confirm that all the models were the latest versions.However, when I tested it in Xcode, everything was normal without any errors. Here is my MigrationPlan code: import Foundation import SwiftData enum MeMigrationPlan: SchemaMigrationPlan { static var schemas: [any VersionedSchema.Type] { [MeSchemaV1.self, MeSchemaV2.self, MeSchemaV3.self, MeSchemaV4.self] } static var stages: [MigrationStage] { [migrateV1toV2, migrateV2toV3, migrateV3toV4] } //migrateV1toV2, because the type of a data field in MeSchemaV1.TodayRingData.self was modified, the historical data was deleted during the migration, and the migration work was successfully completed. static let migrateV1toV2 = MigrationStage.custom( fromVersion: MeSchemaV1.self, toVersion: MeSchemaV2.self, willMigrate: { context in try context.delete(model: MeSchemaV1.TodayRingData.self) }, didMigrate: nil ) //migrateV2toV3, because a new Model was added, it would crash at startup when TF and the official version were updated, so I tried to delete the historical data during migration, but the problem still exists. static let migrateV2toV3 = MigrationStage.custom( fromVersion: MeSchemaV2.self, toVersion: MeSchemaV3.self, willMigrate: { context in try context.delete(model: MeSchemaV2.TodayRingData.self) try context.delete(model: MeSchemaV2.HealthDataStatistics.self) try context.delete(model: MeSchemaV2.SportsDataStatistics.self) try context.delete(model: MeSchemaV2.UserSettingTypeFor.self) try context.delete(model: MeSchemaV2.TodayRingData.self) try context.delete(model: MeSchemaV2.TodayHealthData.self) try context.delete(model: MeSchemaV2.SleepDataSource.self) try context.delete(model: MeSchemaV2.WorkoutTargetData.self) try context.delete(model: MeSchemaV2.WorkoutStatisticsForTarget.self) try context.delete(model: MeSchemaV2.HealthDataList.self) }, didMigrate: nil ) //migrateV3toV4, adds some fields in MeSchemaV3.WorkoutList.self, and adds several new Models. When TF and the official version are updated, it will crash at startup. Continue to try to delete historical data during migration, but the problem still exists. static let migrateV3toV4 = MigrationStage.custom( fromVersion: MeSchemaV3.self, toVersion: MeSchemaV4.self, willMigrate: { context in do { try context.delete(model: MeSchemaV3.WorkoutList.self) try context.delete(model: MeSchemaV3.HealthDataStatistics.self) try context.delete(model: MeSchemaV3.SportsDataStatistics.self) try context.delete(model: MeSchemaV3.UserSettingTypeFor.self) try context.delete(model: MeSchemaV3.TodayRingData.self) try context.delete(model: MeSchemaV3.TodayHealthData.self) try context.delete(model: MeSchemaV3.SleepDataSource.self) try context.delete(model: MeSchemaV3.WorkoutTargetData.self) try context.delete(model: MeSchemaV3.WorkoutStatisticsForTarget.self) try context.delete(model: MeSchemaV3.HealthDataList.self) try context.delete(model: MeSchemaV3.SleepStagesData.self) try context.save() } catch { print("Migration from V3 to V4 failed with error: \(error)") throw error } }, didMigrate: nil ) }
18
0
435
1w
SwiftData crash: PersistentModel.keyPathToString(keypath:)
I'm distributing an iOS (17.4+) and visionOS (1.2+) app via TestFlight that's using SwiftData. The most common crash by far is from SwiftData when deleting models from a context using a predicate (first snippet below), but so far I've been unable to reproduce it myself locally (second snippet below). I'm using SwiftData outside of SwiftUI views, via my own wrapper, and converting between my app models and SwiftData models. Does anyone have any ideas how I could potentially narrow this issue down (or reproduce), or know of any similar issues? Thanks! — Seb do { try context.transaction { context in let predicate = #Predicate<PersistedFeed> { $0.id == id } do { try context.delete(model: PersistedFeed.self, where: predicate) } catch { // .. Omitted for brevity } } } catch { // .. Omitted for brevity } Crash: Thread 0 Crashed: 0 libswiftCore.dylib 0x000000018dd558c0 _assertionFailure(_:_:file:line:flags:) + 264 (AssertCommon.swift:144) 1 SwiftData 0x000000022f7f323c static PersistentModel.keyPathToString(keypath:) + 1496 (DataUtilities.swift:0) 2 SwiftData 0x000000022f83312c PredicateExpressions.KeyPath.convert(state:) + 492 (FetchDescriptor.swift:394) 3 SwiftData 0x000000022f834a24 protocol witness for ConvertibleExpression.convert(state:) in conformance PredicateExpressions.KeyPath<A, B> + 16 (<compiler-generated>:0) 4 SwiftData 0x000000022f830a70 PredicateExpression.convertToExpressionOrPredicate(state:) + 724 (FetchDescriptor.swift:203) 5 SwiftData 0x000000022f831874 PredicateExpression.convertToExpression(state:) + 36 (FetchDescriptor.swift:217) 6 SwiftData 0x000000022f83b6c8 PredicateExpressions.Equal.convert(state:) + 328 7 SwiftData 0x000000022f8360ec protocol witness for ConvertibleExpression.convert(state:) in conformance PredicateExpressions.Equal<A, B> + 64 (<compiler-generated>:0) 8 SwiftData 0x000000022f830a70 PredicateExpression.convertToExpressionOrPredicate(state:) + 724 (FetchDescriptor.swift:203) 9 SwiftData 0x000000022f82fd60 PredicateExpression.convertToPredicate(state:) + 28 (FetchDescriptor.swift:224) 10 SwiftData 0x000000022f82edb4 nsPredicate<A>(for:) + 956 (FetchDescriptor.swift:88) 11 SwiftData 0x000000022f807c2c ModelContext.delete<A>(model:where:includeSubclasses:) + 596 (ModelContext.swift:1846) 12 SwiftData 0x000000022f81994c dispatch thunk of ModelContext.delete<A>(model:where:includeSubclasses:) + 56
0
0
194
3w
Is SwiftData's #Unique currently broken or am I missing something?
Hi, I am inserting two models where the "unique" attribute is the same. I was under the impression, that this should result in an upsert and not two inserts of the model, but that is not the case. See the test coding below for what I am doing (it is self contained, so if you want to try it out, just copy it into a test target). The last #expect statement fails because of the two inserts. Not sure if this is a bug (Xcode 16 beta 2 on Sonoma running an iOS 18 simulator) or if I am missing something here... // MARK: - UniqueItem - @Model final class UniqueItem { #Unique<UniqueItem>([\.no]) var timestamp = Date() var title: String var changed = false var no: Int init(title: String, no: Int) { self.title = title self.no = no } } // MARK: - InsertTests - @Suite("Insert Tests", .serialized) struct InsertTests { var sharedModelContainer: ModelContainer = { let schema = Schema([ UniqueItem.self, ]) let modelConfiguration = ModelConfiguration(schema: schema, isStoredInMemoryOnly: false) do { return try ModelContainer(for: schema, configurations: [modelConfiguration]) } catch { fatalError("Could not create ModelContainer: \(error)") } }() @Test("Test unique.") @MainActor func upsertAndModify() async throws { let ctx = sharedModelContainer.mainContext try ctx.delete(model: UniqueItem.self) let item = UniqueItem(title: "Item \(1)", no: 0) ctx.insert(item) let allFD = FetchDescriptor<UniqueItem>() let count = try ctx.fetchCount(allFD) #expect(count == 1) let updatedItem = UniqueItem(title: "Item \(1)", no: 0) updatedItem.changed = true ctx.insert(updatedItem) // we should still have only 1 item because of the unique constraint let allCount = try ctx.fetchCount(allFD) #expect(allCount == 1) } }
0
1
213
3w
SwfitData Crashes after MigrationPlan Completed
There are multiple versions of VersionedSchema in my App. I used MigrationPlan to migrate data. It works well in Xcode, but in TestFlight and App Store, it always crashes when opening the App for the first time. MeMigrationPlan Code: import Foundation import SwiftData enum MeMigrationPlan: SchemaMigrationPlan { static var schemas: [any VersionedSchema.Type] { [MeSchemaV1.self, MeSchemaV2.self, MeSchemaV3.self, MeSchemaV4.self] } static var stages: [MigrationStage] { [migrateV1toV2, migrateV2toV3, migrateV3toV4] } //migrateV1toV2, because the type of a data field in MeSchemaV1.TodayRingData.self is modified, the historical data is deleted during migration, and the migration work is successfully completed. static let migrateV1toV2 = MigrationStage.custom( fromVersion: MeSchemaV1.self, toVersion: MeSchemaV2.self, willMigrate: { context in try context.delete(model: MeSchemaV1.TodayRingData.self) }, didMigrate: nil ) //migrateV2toV3, because a new Model was added, it would crash when starting up when TF and the official version were updated, so I tried to delete the historical data during migration, but the problem still exists. static let migrateV2toV3 = MigrationStage.custom( fromVersion: MeSchemaV2.self, toVersion: MeSchemaV3.self, willMigrate: { context in try context.delete(model: MeSchemaV2.TodayRingData.self) try context.delete(model: MeSchemaV2.HealthDataStatistics.self) try context.delete(model: MeSchemaV2.SportsDataStatistics.self) try context.delete(model: MeSchemaV2.UserSettingTypeFor.self) try context.delete(model: MeSchemaV2.TodayRingData.self) try context.delete(model: MeSchemaV2.TodayHealthData.self) try context.delete(model: MeSchemaV2.SleepDataSource.self) try context.delete(model: MeSchemaV2.WorkoutTargetData.self) try context.delete(model: MeSchemaV2.WorkoutStatisticsForTarget.self) try context.delete(model: MeSchemaV2.HealthDataList.self) }, didMigrate: nil ) //migrateV3toV4, adds some fields in MeSchemaV3.WorkoutList.self, and adds several new Models. When TF and the official version are updated, it will crash at startup. Continue to try to delete historical data during migration, but the problem still exists. static let migrateV3toV4 = MigrationStage.custom( fromVersion: MeSchemaV3.self, toVersion: MeSchemaV4.self, willMigrate: { context in do { try context.delete(model: MeSchemaV3.WorkoutList.self) try context.delete(model: MeSchemaV3.HealthDataStatistics.self) try context.delete(model: MeSchemaV3.SportsDataStatistics.self) try context.delete(model: MeSchemaV3.UserSettingTypeFor.self) try context.delete(model: MeSchemaV3.TodayRingData.self) try context.delete(model: MeSchemaV3.TodayHealthData.self) try context.delete(model: MeSchemaV3.SleepDataSource.self) try context.delete(model: MeSchemaV3.WorkoutTargetData.self) try context.delete(model: MeSchemaV3.WorkoutStatisticsForTarget.self) try context.delete(model: MeSchemaV3.HealthDataList.self) try context.delete(model: MeSchemaV3.SleepStagesData.self) try context.save() } catch { print("Migration from V3 to V4 failed with error: \(error)") throw error } }, didMigrate: nil ) }
1
0
139
3w
SwiftData via CloudKit Only Syncing Upon Relaunch
Hello I'm a new developer and am learning the ropes. I have an app that I'm testing and seem to have run into a bug. The data is syncing from one device to another, however it takes closing the app on the Mac or force closing the app on iOS/iPadOS to get the app to reflect the new data. Is there specific code I code share to help solve this issue or any suggestions that someone may have? Thank you ahead of time for your assistance. import SwiftData @main struct ApplicantProcessorApp: App { var sharedModelContainer: ModelContainer = { let schema = Schema([ Applicant.self, ]) let modelConfiguration = ModelConfiguration(schema: schema, isStoredInMemoryOnly: false) do { return try ModelContainer(for: schema, configurations: [modelConfiguration]) } catch { fatalError("Could not create ModelContainer: \(error)") } }() var body: some Scene { WindowGroup { ContentView() } .modelContainer(sharedModelContainer) } } struct ContentView: View { var body: some View { FilteredApplicantListView() } } #Preview { ContentView() .modelContainer(SampleData.shared.modelContainer) } struct FilteredApplicantListView: View { @State private var searchText = "" var body: some View { NavigationSplitView { ApplicantListView(applicantFilter: searchText) .searchable(text: $searchText, prompt: "Enter Name, Email, or Phone Number") .autocorrectionDisabled(true) } detail: { } } } import SwiftData struct ApplicantListView: View { @Environment(\.modelContext) private var modelContext @Query private var applicants: [Applicant] @State private var newApplicant: Applicant? init(applicantFilter: String = "") { // Filters } var body: some View { Group { if !applicants.isEmpty { List { ForEach(applicants) { applicant in NavigationLink { ApplicantView(applicant: applicant) } label: { HStack { VStack { HStack { Text(applicant.name) Spacer() } HStack { Text(applicant.phoneNumber) .font(.caption) Spacer() } HStack { Text(applicant.email) .font(.caption) Spacer() } HStack { Text("Expires: \(formattedDate(applicant.expirationDate))") .font(.caption) Spacer() } } if applicant.applicationStatus == ApplicationStatus.approved { Image(systemName: "checkmark.circle") .foregroundStyle(.green) .font(.title) } else if applicant.applicationStatus == ApplicationStatus.declined { Image(systemName: "xmark.circle") .foregroundStyle(.red) .font(.title) } else if applicant.applicationStatus == ApplicationStatus.inProgress { Image(systemName: "hourglass.circle") .foregroundStyle(.yellow) .font(.title) } else if applicant.applicationStatus == ApplicationStatus.waitingForApplicant { Image(systemName: "person.circle") .foregroundStyle(.yellow) .font(.title) } else { Image(systemName: "yieldsign") .foregroundStyle(.yellow) .font(.title) } } } } .onDelete(perform: deleteItems) } } else { ContentUnavailableView { Label("No Applicants", systemImage: "pencil.fill") } } } .navigationTitle("Applicants") .toolbar { ToolbarItem(placement: .navigationBarTrailing) { EditButton() } ToolbarItem { Button(action: addApplicant) { Label("Add Item", systemImage: "plus") } } } .sheet(item: $newApplicant) { applicant in NavigationStack { ApplicantView(applicant: applicant, isNew: true) } } } private func addApplicant() { withAnimation { let newItem = Applicant() modelContext.insert(newItem) newApplicant = newItem } } private func deleteItems(offsets: IndexSet) { withAnimation { for index in offsets { modelContext.delete(applicants[index]) } } } func formattedDate(_ date: Date) -> String { let dateFormatter = DateFormatter() dateFormatter.dateStyle = .short dateFormatter.timeStyle = .none return dateFormatter.string(from: date) } } import SwiftData @Model final class Applicant { var name = "" var email = "" var phoneNumber = "" var applicationDate = Date.now var expirationDate: Date { return Calendar.current.date(byAdding: .day, value: 90, to: applicationDate)! }
1
0
222
3w
SwiftData fatal error "Never access a full future backing data"
My app started crashing a ton with Xcode 16 beta 1 / iOS 18 because of "Thread 1: Fatal error: Never access a full future backing data". I was hoping this would be resolved with beta 2, but unfortunately this is not the case. I'm having a tough time reproducing this bug in a small sample project – I'd appreciate any hints as to what might be causing this. Full error: Thread 1: Fatal error: Never access a full future backing data - PersistentIdentifier(id: SwiftData.PersistentIdentifier.ID(url: x-coredata://10A5A93C-DC7F-40F3-92DB-F4125E1C7A73/MyType/p2), implementation: SwiftData.PersistentIdentifierImplementation) with Optional(3BF44A2D-256B-4C40-AF40-9B7518FD9FE6)
5
4
405
2w
How to embed SwiftData model container in a custom file package document type
Hi all, I have done a lot of research on this but am not able to come up with a workable solution. Background: I am trying to make an universal app on macOS/iOS that organizes media (image/video/pdf); think of its functionality like Apple's Photos app. So for my app document type, I would have my custom file package and within the package folder, there would be a SwiftData model container file and folders to hold user media. Approaches taken: DocumentGroup with SwiftData model then write directly into the file package In my App scene, I create document by having DocumentGroup(editing: .customDocument, migrationPlan: CustomMigrationPlan.self). This will create a document with a model container with my SwiftData model. And when I need to add media files into the document, I get the URL of the document, then use FileManager to write the file into the desired folder in the document. The result is that the media file is saved in the file package but then the SwiftData container is corrupted (all model data is reset to empty.) I am now trying to: 2. DocumentGroup with custom file package then try to embed SwiftData container In my current approach, I would create a document by having DocumentGroup(newDocument: CustomFileDocument()). I have custom FileDocument and FileWrapper. But the problem is I don't know how to embed a SwiftData container into my FileDocument. Is it possible to create a SwiftData model container when my FilerWrapper initialize? I can't figure out how to do this. Can anyone please advice on how I should accomplish this? Or if maybe I am looking at this problem wrongly? Do I need to use AppKit/UIKit with Core Data because it's currently not possible with SwiftUI/SwiftData? Thank you so much for reading and any input is greatly appreciated.
0
0
187
3w