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.

SwiftData Documentation

Posts under SwiftData tag

502 Posts
Sort by:
Post not yet marked as solved
0 Replies
22 Views
Hi! Not sure if this is a swift data or more a Decimal in general type of question. What's going on: I have a SwiftUI app using SwiftData, I have persisted a Model with a property "reducedPrice" of type Decimal. It's stores correctly the value. Now, I have read the value during automated tests and tried comparing the values: let reducedPrice = model.reducedPrice // swift data property let target = Decimal(4.98) // expected target value to compare to swift data value. Now if I just print the result of the comparison between those 2 I get a false result. print(reducedPrice == target) //output : false The swift data model was populated from a direct copy of another struct that comes from an JSON import using Codable+CodingKeys (I used Decimal type). What I expected: I expected it to be true. Debug Observations I did noticed that on the variable inspector both had the same magnitudes but in reality the mantissa are different. I'm attaching a screenshot. My Theory They are different just because something under SwiftData stores different way the decimal as in comparison on how I am creating the Decimal for the comparison inside the automated tests. My question Is this expected behavior? Any suggestion on best practices on how to handle this? Thank you in advance any relevant guidance is very appreciated!
Posted
by joe_dev.
Last updated
.
Post not yet marked as solved
0 Replies
40 Views
I'm developing an app with a chart in SwiftUI. I want the following block of code to run when the chart is clicked. On my personal iPhone, the app works flawlessly. But when I try it in the simulator it crashes and gives me about 5-10 of the following errors. When I remove the @Query macro from the code block, the application does not crash in the simulator, but I continue to get the errors I mentioned. If I do not run the following code block, I do not get the errors I mentioned. struct SaleDetailView: View { @Query(filter: #Predicate<Registration> { !$0.activeRegistration }) private var regs: [Registration] var body: some View { VStack { DailySaleView() } .padding() } } Thank you in advance for your answers. Do not hesitate to ask if you have any questions. Thanks, MFS
Posted Last updated
.
Post not yet marked as solved
2 Replies
132 Views
Dear all, I have the following two classes: Stagioni: import SwiftData @Model class Stagione { @Attribute(.unique) var idStagione: String var categoriaStagione: String var miaSquadra: String @Relationship(deleteRule: .cascade) var rosa: [Rosa]? @Relationship(deleteRule: .cascade) var squadra: [Squadre]? @Relationship(deleteRule: .cascade) var partita: [CalendarioPartite]? init(idStagione: String, categoriaStagione: String, miaSquadra: String) { self.idStagione = idStagione self.categoriaStagione = categoriaStagione self.miaSquadra = miaSquadra } } CalendarioPartite: import SwiftData @Model class CalendarioPartite { var idGiornata: Int var dataPartita: Date var squadraCasa: String var squadraTrasferta: String var golCasa: Int var golTrasferta: Int var stagione: Stagione? init(idGiornata: Int, dataPartita: Date, squadraCasa: String, squadraTrasferta: String, golCasa: Int, golTrasferta: Int) { self.idGiornata = idGiornata self.dataPartita = dataPartita self.squadraCasa = squadraCasa self.squadraTrasferta = squadraTrasferta self.golCasa = golCasa self.golTrasferta = golTrasferta } } Now, I'd like to have a query which is showing in a view the list of partite depending on a selection of a specific Stagione. I've tried with the following query, but I'm getting the following error: "Instance member 'selectedStagione' cannot be used on type 'CalendarioCampionatoView'; did you mean to use a value of this type instead?" @Query(filter: #Predicate<CalendarioPartite> { $0.stagione == selectedStagione}) private var partite: [CalendarioPartite] = [] What I'm doing wrong? Thanks, A.
Posted
by AndreB82.
Last updated
.
Post not yet marked as solved
1 Replies
94 Views
Can anyone give me assistance on how to fix this. My preview crashed because a Fatal Error in ModelData. This is how my ModelData looks: import SwiftUI struct SutraokeDetail: View { @Environment(ModelData.self) var modelData var sutra: Sutras var body: some View { @Bindable var modelData = modelData ScrollView { CircleImage(image: sutra.image) .offset(y: -130) .padding(.bottom, -130) VStack(alignment: .leading) { HStack{ Text(sutra.name) .font(.title) Spacer() Text(sutra.text) } } } } } #Preview { let modelData = ModelData() return SutraokeDetail(sutra: modelData.sutras[0]) .environment(modelData) }
Posted
by Kuralay.
Last updated
.
Post not yet marked as solved
0 Replies
81 Views
UPDATED: I determined the line causing the hang was .animation(.default, value: layout). I'm seeing a strange issue when switching between a ScrollView/LazyVGrid and a List with my SwiftData but when toggling the layout it ends up freezing and I can't confirm what's causing the app to hang since there's no crash. I'm not getting much info from the debugger. Any help would be appreciated. struct ContentView: View { @Environment(\.modelContext) private var modelContext @Query private var items: [Item] let gridItemLayout = [ GridItem(.adaptive(minimum: 150))] @State private var layout = Layout.grid var body: some View { NavigationStack { ZStack { if layout == .grid { ScrollView { LazyVGrid(columns: gridItemLayout, spacing: 5) { ForEach(items) { item in } } } } else { List { ForEach(items) { item in } } } } // MARK: HERE'S THE ERROR .animation(.default, value: layout) .navigationTitle("ScrollView") .toolbar { ToolbarItemGroup { Button(action: addItem) { Label("Add Item", systemImage: "plus") } Menu { Picker("Layout", selection: $layout) { ForEach(Layout.allCases) { option in Label(option.title, systemImage: option.imageName) .tag(option) } } .pickerStyle(.inline) } label: { Label("Layout Options", systemImage: layout.imageName) .labelStyle(.iconOnly) } } } } } } @Model public class Item: Codable { public let id: String public enum CodingKeys: String, CodingKey { case id } public init(id: String) { self.id = id } required public init(from decoder: Decoder) throws { let container = try decoder.container(keyedBy: CodingKeys.self) id = try container.decode(String.self, forKey: .id) } public func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) try container.encode(id, forKey: .id) } }
Posted Last updated
.
Post not yet marked as solved
1 Replies
92 Views
SwiftData includes support for CloudKit sync. However, I don't see any way to add conflict resolution behavior. For example, if different devices set different values for a field, or if a relationship is orphaned because of a deletion on another device, the application has to handle this somehow. In Core Data (which SwiftData wraps), you can handle this with the conflict resolution system (docs) and classes like NSMergePolicy. Is any of this accessible in SwiftData? If not, how do you deal with conflicts when syncing a SwiftData model with the cloud?
Posted Last updated
.
Post not yet marked as solved
2 Replies
154 Views
Has anyone successfully persisted Color, particularly in SwiftData? So far my attempts have failed: Making Color conform to Codable results in a run time error (from memory something about ColorBox). Color.Resolved already conforms Codable but this results in "SwiftData/ModelCoders.swift:124: Fatal error: Composite Coder only supports Keyed Container" None of the other color types conform to Codable (CGColor, NSColor and UIColor) so does the swift language really not have a persistable color type?
Posted
by Uasmel.
Last updated
.
Post not yet marked as solved
0 Replies
83 Views
Hello everyone, I looked at various methods how to Unit/UITest SwiftData but I couldn't find something simple. Is it even possible to test SwiftData? Does someone found a solution for that?
Posted
by iRIG.
Last updated
.
Post not yet marked as solved
0 Replies
91 Views
I have a situation where tapping on a NavigationLink on an item from a SwiftData Query results in an infinite loop, causing the app the freeze. If you run the code, make sure to add at least 1 item, then tap on it to see the issue. Here is the code for a small sample app I made to illustrate the issue: import SwiftUI import SwiftData @main struct TestApp: App { var sharedModelContainer: ModelContainer = { let schema = Schema([ Item.self ]) let modelConfiguration = ModelConfiguration(schema: schema, isStoredInMemoryOnly: false) do { let container = try ModelContainer(for: schema, configurations: [modelConfiguration]) return container } catch { fatalError("Could not create ModelContainer: \(error)") } }() var body: some Scene { WindowGroup { ContentView() } .modelContainer(sharedModelContainer) } } struct ContentView: View { var body: some View { NavigationStack { ListsView() } } } struct ListsView: View { @Environment(\.modelContext) private var modelContext @Query(filter: #Predicate<Item> { _ in true }) private var items: [Item] var body: some View { List(items) { item in NavigationLink { ItemDetail() } label: { VStack { Text("\(item.name) | \(item.date.formatted())") } } } Button("Add") { let newItem = Item(name: "Some item", date: .now) modelContext.insert(newItem) try? modelContext.save() } } } struct ItemDetail: View { private var model = ItemModel() var body: some View { VStack { Text("detail") } } } fileprivate var count = 0 class ItemModel { var value: Int init() { value = 99 print("\(count)") count += 1 } } @Model final class Item { let name: String let date: Date init(name: String, date: Date) { self.name = name self.date = date } } In the test app above, the code in the initializer of ItemModel will run indefinitely. There are a few things that will fix this issue: comment out the private var model = ItemModel() line in ItemDetail view replace the @Query with a set list of Items move the contents of the ListsView into the ContentView instead of referencing ListsView() inside the NavigationStack But I'm not sure why this infinite loop is happening with the initializer of ItemModel. It seems like a SwiftData and/or SwiftUI bug, because I don't see a reason why this would happen. Any ideas? Has anyone run into something similar?
Posted Last updated
.
Post marked as solved
2 Replies
96 Views
I have been working on an ios application which I decided to use the new SwiftData architecture, and I now have realized that SwiftData does not support public or shared databases using SwiftData. I am a new and upcoming Swift developer, who has been self learning the Apple Swift technology. I just learned in this forum that Swift Data does not support Public and Shared Data and I also understand that no plans that have been announced to addressed this feature in the IOS 18 release time frame. The use case for my application is to implement a social type application, something like applications including X, facebook, etc. These type of applications appear to use Public, Shared and Private data in various existing Apple application. I would like to complete an application using Swift using ICloud, but I must assume that these current social applications are using other technologies. I am assuming you can do this in Core Data, but my understanding is Apple is asking that we use Swift Data to replace core data. I also am assuming that Swift data is built on core data technology layers. So ... to me it seems hopeful, somehow, to accomplish this using IOS 17 and follow the recommend Swift Data Path. What are my options for completing these data objectives in IOS? I hope I am addressing these questions in the proper and best forum? Much thanks for any suggestions.
Posted
by bxw0405.
Last updated
.
Post not yet marked as solved
1 Replies
91 Views
I have an Apple app that uses SwiftData and icloud to sync the App's data across users' devices. Everything is working well. However, I am facing the following issue: SwiftData does not support public sharing of the object graph with other users via iCloud. How can I overcome this limitation without stopping using SwiftData? Thanks in advance!
Posted
by olopul.
Last updated
.
Post not yet marked as solved
2 Replies
702 Views
It's been frustrating to solve this error. My iOS device and Xcode are fully updated. I can easily run app on simulator, but issue happens on my iPhone. dyld[23479]: Symbol not found: _$s9SwiftData12ModelContextC6insert6objectyx_tAA010PersistentC0RzlFTj Referenced from: <6FC773BB-E68B-35A9-B334-3FFC8B951A4E> Expected in: /System/Library/Frameworks/SwiftData.framework/SwiftData
Posted
by meet__071.
Last updated
.
Post not yet marked as solved
0 Replies
90 Views
I am converting a large core data app to SwiftData and have hit a problem I can't fix, namely code generated by a Model crashing. Here is the model showing the failing expansion. Here is the model containing the inverse for the failing attribute: /Users/writingshedprod/Desktop/Screenshot 2024-05-08 at 20.21.51.png And here is the mass of core data output generated when the app launches. If anyone can make sense of this I'd be grateful. This is where the problem might lie. Debugger.txt
Posted Last updated
.
Post marked as solved
1 Replies
105 Views
I'm getting an "No exact matches in call to instance method 'setValue'" error for a property that has a enum as a value. How do I fix this? Any help would be appreciated. enum FluidUnit: CaseIterable, Identifiable { case ounce, liter var id: Self { self } var title: String { switch self { case .ounce: return "ounce" case .liter: return "liters" } } } @Model class Drink: Identifiable, Hashable { let id: UUID = UUID() let name: String = "" var shortName: String = "" var amount: Double = 0.0 let unitOfMeasure: FluidUnit = FluidUnit.ounce let date: Date = Date() var image: String = "water" var favorite: Bool = false init(name: String, amount: Double, unitOfMeasure: FluidUnit, image: String, favorite: Bool = false, shortName: String = "") { self.id = UUID() self.name = name self.amount = amount self.unitOfMeasure = unitOfMeasure self.date = Date() self.image = image self.favorite = favorite self.shortName = shortName } static func == (lhs: Drink, rhs: Drink) -> Bool { lhs.id == rhs.id } func hash(into hasher: inout Hasher) { hasher.combine(id) } }
Posted
by syclonefx.
Last updated
.
Post marked as solved
3 Replies
490 Views
I'm using two loops, one nested in another to create and assign a subclass to the parent class. I'm using x for one loop and y for the other loop. Print statement shows the loop variables being updated correctly, however the subclass has both variables as the same value. I'm not sure if the value is being stored as the same value or being displayed as the same value. I've checked both creation and display code. I can't find the error. var body: some View { NavigationSplitView { List { ForEach(routes) { item in NavigationLink { Text("Route: \(item.route_name) \nSeason: \(item.route_season)\nCoordinates: \(item.route_coordinates)\nProcessed: \(String(item.route_processed))\nNumber of baseboards: \(item.route_baseboards.count)") } label: { Text(item.route_name) } //end route nav link } //end route for each .onDelete(perform: deleteItems) //end route nav ForEach(baseboards) { item in NavigationLink { //if let test = item.baseboard_heightPoints.count { Text("Grid Size: \(String(item.baseboard_grid_size))\nRow:\(String(item.baseboard_row))\nColumn:\(String(item.baseboard_column))\nHeight Point Count:")//\(String(item.baseboard_heightPoints.flatMap { $0 } .count))") //fix count later //Text("Test") // Text("test2") // } else { // Text("Grid Size: \(String(item.baseboard_grid_size))\nRow:\(String(item.baseboard_row))\nColumn:\(String(item.baseboard_column))\nHeight Point Count: 0") // } } label: { Text(String(item.baseboard_grid_size)) }} .onDelete(perform: deleteItemsBaseboards) //end baseboard route nav // ForEach(heightPoints) { item in NavigationLink { // Text("Row:\(String(item.hp_row))\nColumn:\(String(item.hp_column))\nElevation:\(String(item.hp_elevation))") // } label: { // Text("Row:\(String(item.hp_row))\nColumn:\(String(item.hp_column))") // }} //.onDelete(perform: deleteItemsBaseboards) } .toolbar { ToolbarItem { Button(action: addItem) { Label("Add Route", systemImage: "plus") } //Button(action: addItem) { //not showing up // Label("Add Baseboard", systemImage: "arrow.up") //} } } //end toolbar } detail: { Text("Select a route") } //end NavigationSplitView } //end view body private func addItem() { /*withAnimation { */ let newItem = Route( route_name: "test route " + UUID().uuidString, route_season: "summer", route_processed: false, route_coordinates: "Somewhere", route_region: "US", route_baseboards: []) modelContext.insert(newItem) //end add route //add baseboards to each route let bb_StartCol = 0 let bb_EndCol = 3 let bb_StartRow = 0 let bb_EndRow = 3 //let grid5m = 148 //let grid10m = 76 //let gridHD = 5760 var bb_grid_size = 5760 let bb_sectionsVerticle = 180 let bb_sectionsHorizonal = 360 var sectionData: Data var dataInputArray: [UInt8] = [0x03, 0x00, 0x00, 0x00, 0x00, 0x82, 0xFF, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x20, 0xF8, 0xFF] sectionData = Data(withUnsafeBytes(of: dataInputArray, Array.init)) for x in bb_StartCol...bb_EndCol { //columns for y in bb_StartRow...bb_EndRow { //rows print(x,y) if bb_grid_size < 1000 { let newItem2 = Baseboard( baseboard_column: Int16(x), baseboard_row: Int16(y), texture: "Grid", baseboard_processed: false, baseboard_grid_size: Int16(bb_grid_size),//(x+2)+(y+2), baseboard_heightPoints: Array(repeating: Array(repeating: 0, count: bb_grid_size), count: bb_grid_size), baseboard_HPSection: [], baseboard_route: newItem //baseboard_hps: [] ) modelContext.insert(newItem2) //insert baseboard for each run } else { let newItem2 = Baseboard( baseboard_column: Int16(x), baseboard_row: Int16(y), texture: "Grid", baseboard_processed: false, baseboard_grid_size: Int16(bb_grid_size),//(x+2)+(y+2), baseboard_heightPoints: [], baseboard_HPSection: Array(repeating: Array(repeating: sectionData, count: bb_sectionsVerticle), count: bb_sectionsHorizonal), baseboard_route: newItem //baseboard_hps: [] ) modelContext.insert(newItem2) //insert baseboard for each run } //print(x,y) } //end y for loop - baseboards } //end x for loop - baseboards // } // end animation of adding new items } // end function add items private func deleteItems(offsets: IndexSet) { withAnimation { for index in offsets { modelContext.delete(routes[index]) } } } private func deleteItemsBaseboards(offsets: IndexSet) { withAnimation { for index in offsets { modelContext.delete(baseboards[index]) } } } //private func deleteItemsHeightPoints(offsets: IndexSet) { // withAnimation { // for index in offsets { // modelContext.delete(heightPoints[index]) // } // } // } } #Preview { ContentView() .modelContainer(for: Route.self, inMemory: false) }
Posted
by CapFred.
Last updated
.
Post marked as solved
3 Replies
157 Views
I just purchased a new M3 chip MacBook Air a little after it came out. I was able to create and deploy an iOS application. However, now that I am trying to create a new project Xcode throws an error upon launch. Steps to recreate the error (if possible) Open Xcode Select create new app An error is where the preview should be. At this point I have added no code. It is all boiler plate from Apple.
Posted Last updated
.
Post not yet marked as solved
3 Replies
122 Views
If I annotate a class with @Observable I get this error in @Query: Expansion of macro 'Query()' produced an unexpected 'init' accessor If I remove @Observable the error goes away. Elsewhere I have .environment referencing the class. With @Observable this complains that the class needs to be @Observable. I am mystified. Does anyone have a suggestion?
Posted Last updated
.
Post not yet marked as solved
0 Replies
135 Views
I have spent hours trying to get @Query macros to compile. Mostly they throw up meaningless errors for example the following produces 3 compiler errors: @Query var stylesheets: [StyleSheet] Here's the expansion. The compiler complains that 'private' can't be used here, and it can't find _stylesheets. I searched everywhere to find a resolution then I came across the Query struct. I used it as follows to replace the @Query: let query = Query(FetchDescriptor<StyleSheet>(), animation: .smooth) let styleSheets = query.wrappedValue This also solves another issue that was bugging me - how to get the context when the environment variable is often rejected. All I need to do now is write: let context = query.modelContext None of the WWDC23 SwiftData videos mentions the use of the struct, which is a shame. It feels much like the CoreData approach to fetching data. I hope this helps some of you.
Posted Last updated
.
Post not yet marked as solved
0 Replies
120 Views
Dear all, I'm building an app leveraging SwiftData and I have the following two classes: Stagione: import SwiftData @Model class Stagione { @Attribute(.unique) var idStagione: String var categoriaStagione: String var miaSquadra: String @Relationship(deleteRule: .cascade) var rosa: [Rosa]? @Relationship(deleteRule: .cascade) var squadra: [Squadre]? @Relationship(deleteRule: .cascade) var partita: [CalendarioPartite]? init(idStagione: String, categoriaStagione: String, miaSquadra: String) { self.idStagione = idStagione self.categoriaStagione = categoriaStagione self.miaSquadra = miaSquadra } } Squadre: import SwiftData @Model class Squadre { var squadraCampionato: String var stagione: Stagione? init(squadraCampionato: String) { self.squadraCampionato = squadraCampionato } } Now, I have a view in which I'm calling a sheet to insert some Squadre: // Presenta il foglio per aggiungere una nuova partita GroupBox(label: Text("Dettagli Partita").font(.headline).padding()) { VStack { HStack { Text("Giornata:") TextField("Giornata", text: $idGiornata) .frame(width: 30) .textFieldStyle(RoundedBorderTextFieldStyle()) .padding() } DatePicker("Data Partita:", selection: $dataPartita, displayedComponents: .date) .padding() HStack { Text("Squadra Casa:") .frame(width: 150) TextField("Squadra Casa", text: $squadraCasa) .textFieldStyle(RoundedBorderTextFieldStyle()) .padding() TextField("Gol Casa", text: $golCasa) .textFieldStyle(RoundedBorderTextFieldStyle()) .padding() } HStack { Text("Squadra Trasferta:") .frame(width: 150) TextField("Squadra Trasferta", text: $squadraTrasferta) .textFieldStyle(RoundedBorderTextFieldStyle()) .padding() TextField("Gol Trasferta", text: $golTrasferta) .textFieldStyle(RoundedBorderTextFieldStyle()) .padding() } HStack { Button("Salva") { if let partitaSelezionata = partitaSelezionata { // Se è stata selezionata una partita, aggiorna i suoi dati if let index = partite.firstIndex(where: { $0.id == partitaSelezionata.id }) { partite[index].idGiornata = Int(idGiornata) ?? 0 partite[index].dataPartita = dataPartita partite[index].squadraCasa = squadraCasa partite[index].golCasa = Int(golCasa) ?? 0 partite[index].squadraTrasferta = squadraTrasferta partite[index].golTrasferta = Int(golTrasferta) ?? 0 } } else { // Altrimenti, aggiungi una nuova partita aggiungiPartita(stagione: stagione) } // Chiudi il foglio di presentazione mostraAggiungiPartita = false // Resetta il campo di input idGiornata = "" dataPartita = Date() squadraCasa = "" golCasa = "" squadraTrasferta = "" golTrasferta = "" } .buttonStyle(.borderedProminent) .disabled(idGiornata.isEmpty || squadraCasa.isEmpty || squadraTrasferta.isEmpty || golCasa.isEmpty || golTrasferta.isEmpty) // Bottone Chiudi Button("Chiudi") { mostraAggiungiPartita = false } .buttonStyle(.borderedProminent) } } .padding() } } I'd like to insert a autocomplete function in the textfields "Squadra Casa" and "Squadra Trasferta", based on the list of Squadre contained in the class "Squadre" and filtered for a specific Stagione. Has anybody of you made something similar? Do you have any suggestions or code example which I can use? Thanks, A.
Posted
by AndreB82.
Last updated
.
Post marked as solved
4 Replies
519 Views
I am currently working on an app that uses the CLMonitor to check when the user has entered a specific region. When the user enters the region, a new region should be monitored, and the old region should be removed. Currently, I have a startMonitoring() method that contains the event handling logic: func startMonitoringConditions() { Task { monitor = await CLMonitor(MonitorNames.monitorName) if let identifiers = await monitor?.identifiers { if identifiers.count == 0 { if let coordinate = manager.location?.coordinate { await addNewRegionAtCoordinate(coordinate: coordinate) } } else { print("Previous Monitor Region is used.") } } for try await event in await monitor!.events { if let coordinate = manager.location?.coordinate { // do something... await monitor!.remove(event.identifier) await addNewRegionAtCoordinate(coordinate: coordinate) } } } } Unfortunately, adding a new region will not update the events collection in the CLMonitor, so the new region's events will not be handled in this method. Any help on how I could fix this problem would be greatly appreciated!
Posted
by selvi.
Last updated
.