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

493 Posts
Sort by:
Post marked as solved
1 Replies
20 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
Post not yet marked as solved
0 Replies
52 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
Post marked as solved
3 Replies
120 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
by
Post not yet marked as solved
1 Replies
95 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
Post not yet marked as solved
0 Replies
104 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
by
Post not yet marked as solved
0 Replies
95 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
Post not yet marked as solved
3 Replies
88 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
by
Post not yet marked as solved
1 Replies
92 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
Post not yet marked as solved
0 Replies
96 Views
A few months back, I launched an app that operated solely on a local level. Recently, I've begun the process of integrating it with CloudKit, and so far, the model integration has been successful. I've utilized SwiftData for this task, making it relatively straightforward to adjust the models, as shown below: ` @Relationship(deleteRule: .cascade, inverse: \ItemForCategory.category) var itemForCategory : [ItemForCategory]? = [ItemForCategory]() ` In my initial version of the code, the widget functioned perfectly. However, I've encountered an error recently stating Missing return in instance method expected to return 'ItemForCategory?'. @MainActor private func getLastItem () -> ItemForCategory? { guard let modelContainer = try? ModelContainer(for: Category.self) else { return nil } let descriptor = FetchDescriptor<Category>() let appCategories = try? modelContainer.mainContext.fetch(descriptor) let lastItem = appCategories?.compactMap { $0.itemForCategory }.last return lastItem } The error surfaces at the return line of code. I'm hopeful that someone can assist me in resolving this issue. Thank you very much.
Posted
by
Post not yet marked as solved
0 Replies
102 Views
I am new to swift. This is my Item.swift. import SwiftData @Model final class Item: Codable { var id: String var soundId: String var soundAppleId: String var soundType: String var type: String var authorId: String var text: String var createdAt: Date var actionsCount: Int var chainsCount: Int var rating: Int var loved: Bool var replay: Bool var heartedByUser: Bool @Relationship var author: Author? init(id: String, soundId: String, soundAppleId: String, soundType: String, type: String, authorId: String, text: String, createdAt: Date, actionsCount: Int, chainsCount: Int, ratings: Int, loved: Bool, replay: Bool, heartedByUser: Bool, author: Author) { self.id = id self.soundId = soundId self.soundAppleId = soundAppleId self.soundType = soundType self.type = type self.authorId = authorId self.text = text self.createdAt = createdAt self.actionsCount = actionsCount self.chainsCount = chainsCount self.rating = ratings self.loved = loved self.replay = replay self.heartedByUser = heartedByUser self.author = author } private enum CodingKeys: String, CodingKey { case id case soundId = "sound_id" case soundAppleId = "sound_apple_id" case soundType = "sound_type" case type case authorId = "author_id" case text case createdAt = "created_at" case actionsCount = "actions_count" case chainsCount = "chains_count" case rating case loved case replay case heartedByUser case author } required init(from decoder: Decoder) throws { let container = try decoder.container(keyedBy: CodingKeys.self) id = try container.decode(String.self, forKey: .id) soundId = try container.decode(String.self, forKey: .soundId) soundAppleId = try container.decode(String.self, forKey: .soundAppleId) soundType = try container.decode(String.self, forKey: .soundType) type = try container.decode(String.self, forKey: .type) authorId = try container.decode(String.self, forKey: .authorId) text = try container.decode(String.self, forKey: .text) let dateString = try container.decode(String.self, forKey: .createdAt) let formatter = DateFormatter() formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'" if let date = formatter.date(from: dateString) { createdAt = date } else { throw DecodingError.dataCorruptedError(forKey: .createdAt, in: container, debugDescription: "Date string does not match format expected by formatter.") } actionsCount = try container.decode(Int.self, forKey: .actionsCount) chainsCount = try container.decode(Int.self, forKey: .chainsCount) rating = try container.decode(Int.self, forKey: .rating) loved = try container.decode(Bool.self, forKey: .loved) replay = try container.decode(Bool.self, forKey: .replay) heartedByUser = try container.decode(Bool.self, forKey: .heartedByUser) author = try container.decode(Author.self, forKey: .author) } func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) try container.encode(id, forKey: .id) try container.encode(soundId, forKey: .soundId) try container.encode(soundAppleId, forKey: .soundAppleId) try container.encode(soundType, forKey: .soundType) try container.encode(type, forKey: .type) try container.encode(authorId, forKey: .authorId) try container.encode(text, forKey: .text) let formatter = DateFormatter() formatter.dateFormat = "yyyy-MM-dd" let dateString = formatter.string(from: createdAt) try container.encode(dateString, forKey: .createdAt) try container.encode(actionsCount, forKey: .actionsCount) try container.encode(chainsCount, forKey: .chainsCount) try container.encode(rating, forKey: .rating) try container.encode(loved, forKey: .loved) try container.encode(replay, forKey: .replay) try container.encode(heartedByUser, forKey: .heartedByUser) try container.encode(author, forKey: .author) } } @Model final class Author: Codable { var id: String var image: URL var username: String var bio: String? init(id: String, image: URL, username: String, bio: String?) { self.id = id self.image = image self.username = username self.bio = bio } private enum CodingKeys: String, CodingKey { case id case image case username case bio } required init(from decoder: Decoder) throws { let container = try decoder.container(keyedBy: CodingKeys.self) id = try container.decode(String.self, forKey: .id) image = try container.decode(URL.self, forKey: .image) username = try container.decode(String.self, forKey: .username) bio = try container.decodeIfPresent(String.self, forKey: .bio) } func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) try container.encode(id, forKey: .id) try container.encode(image, forKey: .image) try container.encode(username, forKey: .username) try container.encodeIfPresent(bio, forKey: .bio) } } In my ItemView when I try to access something inside author, Swift preview crashes. Thread 0 Crashed:: Dispatch queue: com.apple.main-thread 0 SwiftData 0x1cb459e90 0x1cb3d3000 + 552592 1 SwiftData 0x1cb45ba7c 0x1cb3d3000 + 559740 2 SwiftData 0x1cb45e5f8 0x1cb3d3000 + 570872 3 SwiftData 0x1cb4190e4 0x1cb3d3000 + 286948 4 audition 0x100b436e0 Item.author.getter + 320 (@__swiftmacro_8audition4ItemC6author18_PersistedPropertyfMa_.swift:9) 5 ContentView.1.preview-thunk.dylib 0x105f23a20 closure #1 in closure #1 in closure #1 in closure #1 in ItemCard.__preview__body.getter + 820 (ContentView.swift:89) 6 SwiftUI 0x1cba41308 0x1cb47b000 + 6054664 7 ContentView.1.preview-thunk.dylib 0x105f22ee4 closure #1 in closure #1 in closure #1 in ItemCard.__preview__body.getter + 472 (ContentView.swift:84) 8 SwiftUI 0x1cc2e6c40 0x1cb47b000 + 15121472 9 ContentView.1.preview-thunk.dylib 0x105f228b8 closure #1 in closure #1 in ItemCard.__preview__body.getter + 388 (ContentView.swift:83) ...
Posted
by
Post marked as solved
1 Replies
117 Views
I have a Category model that's defined like so: @Model final class Category { @Attribute(.unique) var id: UUID var name: String var parent_id: UUID? //categories can be children of other categories init(id: UUID, name: String, parent_id: UUID?) { self.id = id self.name = name self.parent_id = parent_id } } And I'm getting my categories from an API call and putting it into my View: import SwiftUI import SwiftData struct CategoryView: View { @Environment(\.modelContext) private var modelContext @Query private var categories: [Category] @Query(filter: #Predicate<Category>{ $0.parent_id == nil }) private var top_level_categories: [Category] var spacing: CGFloat = 25 var body: some View { HStack() { Text("Categories") .font(.title.bold()) Spacer() Text("see all") } .padding([.bottom, .top], 0) VStack(spacing: 20) { ScrollView(.horizontal) { HStack(spacing: spacing) { ForEach(top_level_categories) { category in Text(category.name!) } } } } .onAppear{ getCategories() } } func getCategories() { get_refresh_token { token in guard let token = token else { return } var urlRequest = URLRequest (url: URL(string:"https://api.test.com/categories")!) urlRequest.httpMethod = "GET" urlRequest.addValue("application/json", forHTTPHeaderField: "Content-Type") urlRequest.addValue("Bearer \(token)", forHTTPHeaderField: "Authorization") URLSession.shared .dataTask(with: urlRequest) { (data, response, error) in do { if let data = data { let c = try JSONDecoder().decode([Category].self, from: data) c.forEach { modelContext.insert($0) } try? modelContext.save() } } catch { print(error) } }.resume() } } } This runs fine the first time I run the app but when I run it again, I get the following error: ForEach<Array<Category>, UUID, Text>: the ID XXXXXX-XXXX-XXXX-XXXX-XXXXXX occurs multiple times within the collection, this will give undefined results! Not sure why this is happening since I thought putting the @Attribute(.unique) on ID means that the same category won't get added twice?
Posted
by
Post not yet marked as solved
0 Replies
106 Views
I am currently writing an app that is about writing stories. As of now, it is fairly simple: ContentView is your "Collection" of stories. PopupView is when you click on a button in ContentView. In popup view you enter the story title. Once you do that, you are brought to a blank page which is StoryView, where the NavigationTitle is what your story title is. Once I finish the story and leave the page / StoryView, it is still there, but once I close the app on my phone and reopen it, the story is gone and is not saved. I am a relatively new developer, so ive been relying on ChatGPT and Google Gemini for the saving parts of this, but it rarely works, and the furthest ive gotten with it is that it saves the story title but doesn't save the content of the story. I have a feeling that the AI is overdoing it as well. If anyone could help, please do so. Ive been trying to fix this for days. If you need me to provide any code, I am happy to do so. [Edited by Moderator]
Posted
by
Post not yet marked as solved
1 Replies
131 Views
I referred to the code provided in the article Adding and Editing Persistent Data in Your App in the SwiftData documentation and tested the "/PreviewHelper" approach. I found that if a model class contains a property of a struct, and that struct includes a Set property or an Array property, the Preview would throw an error. Here is an example of the model: @Model class Book { // ... var someStruct: SomeStruct // ... } struct SomeStruct: Codable { // ... var someCollection: Set<Int> // ... } In actuality, this model can run and store data without any issues, but it fails to run in the Preview. Is there a problem with the implementation of this Preview or is there any other reason? Are there better ways to perform Preview in SwiftData?
Posted
by
Post not yet marked as solved
1 Replies
148 Views
I know that this has been posted many times, but I am facing an issue where I can't save a model instance. I know that this is due to enums from others trying to find solutions. The error that shows: CoreData: error: Row (pk = 2) for entity 'ResidentInfo' is missing mandatory text data for property 'name' Solutions that I've tried: removed all enums from their respective structs to being standalone. making sure all enum calls use the full keyPath removing CustomStringConvertible from all enums and moving them to rawValue strings updating Xcode to 15.4b probably other things I've forgotten at this point File is too long to fit in post or comments (I'm sorry it's insanely long, it's a complex model), so I'll try to fit what I can where, are there anythings that stand out that may be an issue? Enums: enum Gender: String, CaseIterable, Codable { case male = "Male" case female = "Female" case transmale = "Trans Male" case transfemale = "Trans Female" case nonbinary = "Nonbinary" case other = "Other" } enum BodyBuild: String, CaseIterable, Codable { case small = "Small" case medium = "Medium" case large = "Large" } enum Status: String, Codable { case incomplete, complete } enum HairColor: String, CaseIterable, Codable { case black = "Black" case blonde = "Blonde" case dirtyBlonde = "Dirty Blonde" case brown = "Brown" case lightBrown = "Light Brown" case darkBrown = "Dark Brown" case red = "Red" } enum EyeColor: String, CaseIterable, Codable { case blue = "Blue" case brown = "Brown" case black = "Black" case green = "Green" case hazel = "Hazel" case gray = "Gray" case heterochromatic = "Heterochromatic" } enum RaceEthnicity: String, CaseIterable, Codable { case native = "American Indian or Alaska Native" case asian = "Asian" case black = "Black or African American" case pi = "Native Hawaiian or Other Pacific Islander" case white = "White" case mixed = "2 or More Races/Mixed" } enum MarkType: String, CaseIterable, Codable { case birthMark = "Birth Mark" case scar = "Scar" case tattoo = "Tattoo" case piercing = "Piercing" case other = "Other" } enum heightFormatStyle: String { case short, long, hash } enum suicideRiskLevel: String, Codable { case low = "Low" case medium = "Medium" case high = "High" } enum MedicationFrequency: String, CaseIterable, Codable { case daily = "Daily" case weekly = "Weekly" case biweekly = "Bi-Weekly" case monthly = "Monthly" case asNeeded = "As Needed" case temporary = "Temporary Use" case other = "Other" } enum SchoolOption: String, CaseIterable, Codable { case ged = "GED" case communityCollege = "Community College" case university = "4-Year College" } enum FamilyDiseaseTypes: String, CaseIterable, Codable { case alcoholism = "Alcoholism" case asthma = "Asthma" case cancer = "Cancer" case drugAbuse = "Drug Abuse" case hypertension = "High Blood Pressure" case nervousBreakdown = "Nervous Breakdown" case sca = "Sickle Cell Anemia" case seizures = "Convulsions, Seizures Epilepsy" case allergies = "Allergies" case birthDefect = "Birth Defect" case diabetes = "Diabetes" case heartDisease = "Heart Disease" case migraines = "Migraine Headaches" case obesity = "Obesity" case tuberculosis = "Tuberculosis" case thyroid = "Glandular/Thyroid Issues" } Structs: struct IdentifyingInformation: Codable { var hairColor: HairColor = HairColor.black var height: Height = Height(feet: 5, inches: 8) var race: RaceEthnicity = RaceEthnicity.native var build: BodyBuild = BodyBuild.small var eyeColor: EyeColor = EyeColor.blue var hispanic: Bool = false var distinguishingMarks: [DistinguishingMark] = [] var currentLivingSitutation: String = "" var currentSupportServices: String = "" struct DistinguishingMark: Codable, Identifiable { var id: UUID = UUID() var type: MarkType = MarkType.tattoo var location: String = "" var description: String = "" var photos: [Data] = [] } struct Height: Codable { var feet: Int var inches: Int func formatted(formatStyle: HeightFormatStyle = .short) -> String { switch formatStyle { case HeightFormatStyle.hash: return "\(feet)'\(inches)\"" case HeightFormatStyle.long: return "\(feet) feet \(inches) inches" case HeightFormatStyle.short: return "\(feet)ft \(inches)in" } } } } struct EmergencyNeeds: Codable { var food: Bool = false var shelter: Bool = false var clothing: Bool = false var hygeine: Bool = false var medical: Bool = false var mentalHealth: Bool = false var otherNeeds: String = "" var abuseNeglectAllegations: Bool = false var abuseReport: AbuseReport? = nil struct AbuseReport: Codable { var reportAccepted: Bool = false var whoAccepted: String = "" var reportNumber: String = "" } } struct RiskAssessment: Codable { var selfHarm: Bool = false var selfHarmAttempt: Bool = false var selfHarmExplanation: String? = nil var currentFeelings: String? = nil var dangerToOthers: Bool = false var dangerToOthersExplanation: String? = nil var suicideAssessmentRequired: Bool { return selfHarm || dangerToOthers } } struct SuicideAssessment: Loopable, Codable { var dateCompleted: Date = Date() var familyMember: Bool = false var treatedMentalIllness: Bool = false var chronicIllness: Bool = false var historyOfSelfDestructiveBehavior: Bool = false var recentLoss: Bool = false var isolatedAloneHopeless: Bool = false var goodbyeNoteOrPosessionDelegation: Bool = false var plan: Bool = false var betterOff: Bool = false var wishToDie: Bool = false var manualReview: Bool = false var comments: String = "" var helpCallMade: Bool = false var riskLevel: suicideRiskLevel { let riskScore = try? allProperties().reduce(0) { result, property in if let isTrue = property.value as? Bool, isTrue { return result + 1 } else { return result } } switch riskScore! { case 0 ... 3: return .low case 4 ... 7: return .medium default: return .high } } } [Continued in comments]
Posted
by
Post not yet marked as solved
0 Replies
118 Views
Hi, I'm new to Swift development and encountering an issue that I believe may be due to an error on my part. I have two questions regarding the following code: import AppIntents import SwiftUI import SwiftData @available(iOS 17.0, *) struct CopiarEventoIntent: AppIntent { @Environment(\.modelContext) private var context @Parameter(title: "Nome do Evento") var name: String @Parameter(title: "Data Inicial") var datai: Date @Parameter(title: "Data Final") var dataf: Date @Parameter(title: "Tipo de Evento") var tipo: String @Parameter(title: "Endereço") var endereco: String @Parameter(title: "Lembrete") var reminder: Bool static var title: LocalizedStringResource = "Adicionar Eventos" static var description = IntentDescription("Copiar Eventos e alterar datas", resultValueName: "Resultado") @MainActor func perform() async throws -> some IntentResult & ProvidesDialog { let calData = CalData(title: name, datei: datai, datef: dataf, tipo: tipo, endereco: endereco,reminder: reminder) context.insert(calData) return .result(dialog: "Evento copiado com sucesso!") } } @available(iOS 15.0, *) struct AppShortcuts: AppShortcutsProvider { static var appShortcuts: [AppShortcut] { AppShortcut( intent: CopiarEventoIntent(), phrases: [ "Copiar Evento" ], shortTitle: "Copiar Evento", systemImageName: "square.and.arrow.down" ) } } @available(iOS 15.0, *) struct ShortcutSelectionView: View { @Environment(\.modelContext) private var context @Query(sort: \CalData.title) private var caldatas: [CalData] @State private var selectedEvent: CalData? var body: some View { List(caldatas, id: \.self) { eventData in Button(action: { selectedEvent = eventData handleEventSelection() }) { Text(eventData.title) } } } private func handleEventSelection() { guard selectedEvent != nil else { return } } } When I run the shortcut, gives me the following error: Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Cannot insert 'CalData' in this managed object context because it is not found in the associated managed object model. I attempted to save this using SwiftData with the following model: import SwiftData @Model class CalData { var title : String var datei : Date var datef : Date var tipo : String var endereco : String @Relationship(deleteRule: .cascade) var caldataval = [CalDataVal]() var reminder: Bool = false init(title:String, datei:Date, datef:Date, tipo:String, endereco:String, reminder:Bool){ self.title = title self.datei = datei self.datef = datef self.tipo = tipo self.endereco = endereco self.reminder = reminder } } As for the second question, how can I add a parameter that can have multiple values to save them to EventDataVal, resembling a one-to-many relationship: import SwiftData @Model class CalDataVal { var name : String var value : Double init(name:String, value:Double){ self.name = name self.value = value } } Thanks in advanced
Posted
by
Post not yet marked as solved
0 Replies
180 Views
Hello, I have been working on SwiftData since a month now and i found very weird that every time i update a data inside a SwiftData model my app became very slow. I used the instrument if something was wrong, and i see memory increasing without releasing. My app have a list with check and unchecked elements (screeshot below). I just press check and unchecked 15 times and my memory start from 149mb to 361mb (screenshots below). For the code i have this model. final class Milestone: Identifiable { // ********************************************************************* // MARK: - Properties @Transient var id = UUID() @Attribute(.unique) var uuid: UUID var text: String var goalId: UUID var isFinish: Bool var createdAt: Date var updatedAt: Date var goal: Goal? init(from todoTaskResponse: TodoTaskResponse) { self.uuid = todoTaskResponse.id self.text = todoTaskResponse.text self.goalId = todoTaskResponse.goalId self.isFinish = todoTaskResponse.isFinish self.createdAt = todoTaskResponse.createdAt self.updatedAt = todoTaskResponse.updatedAt } init(uuid: UUID, text: String, goalId: UUID, isFinish: Bool, createdAt: Date, updatedAt: Date, goal: Goal? = nil) { self.uuid = uuid self.text = text self.goalId = goalId self.isFinish = isFinish self.createdAt = createdAt self.updatedAt = updatedAt self.goal = goal } } For the list i have var milestonesView: some View { ForEach(milestones) { milestone in MilestoneRowView(task: milestone) { milestone.isFinish.toggle() } .listRowBackground(Color.backgroundComponent) } .onDelete(perform: deleteMilestone) } And this is the cell struct MilestoneRowView: View { // ********************************************************************* // MARK: - Properties var task: Milestone var action: () -> Void init(task: Milestone, action: @escaping () -> Void) { self.task = task self.action = action } var body: some View { Button { action() } label: { HStack(alignment: .center, spacing: 8) { Image(systemName: task.isFinish ? "checkmark.circle.fill" : "circle") .font(.title2) .padding(3) .contentShape(.rect) .foregroundStyle(task.isFinish ? .gray : .primary) .contentTransition(.symbolEffect(.replace)) Text(task.text) .strikethrough(task.isFinish) .foregroundStyle(task.isFinish ? .gray : .primary) } .foregroundStyle(Color.backgroundComponent) } .animation(.snappy, value: task.isFinish) } } Does someone have a idea? Thanks
Posted
by
Post marked as solved
2 Replies
163 Views
The deletion is working, but it does not refresh the view. This is similar to a question I asked previously but I started a new test project to try and work this out. @Model class Transaction { var timestamp: Date var note: String @Relationship(deleteRule: .cascade) var items: [Item]? init(timestamp: Date, note: String, items: [Item]? = nil) { self.timestamp = timestamp self.note = note self.items = items } func getModifierCount() -> Int { guard let items = items else { return 0 } return items.reduce(0, {result, item in result + (item.modifiers?.count ?? 0) }) } } @Model class Item { var timestamp: Date var note: String @Relationship(deleteRule: .nullify) var transaction: Transaction? @Relationship(deleteRule: .noAction) var modifiers: [Modifier]? init(timestamp: Date, note: String, transaction: Transaction? = nil, modifiers: [Modifier]? = nil) { self.timestamp = timestamp self.note = note self.transaction = transaction self.modifiers = modifiers } } @Model class Modifier { var timestamp: Date var value: Double @Relationship(deleteRule: .nullify) var items: [Item]? init(timestamp: Date, value: Double, items: [Item]? = nil) { self.timestamp = timestamp self.value = value self.items = items } } struct ContentView: View { @Environment(\.modelContext) private var context @Query private var items: [Item] @Query private var transactions: [Transaction] @Query private var modifiers: [Modifier] @State private var addItem = false @State private var addTransaction = false var body: some View { NavigationStack { List { Section(content: { ForEach(items) { item in LabeledText(label: item.timestamp.formatAsString(), value: .int(item.modifiers?.count ?? -1)) } .onDelete(perform: { indexSet in withAnimation { for index in indexSet { context.delete(items[index]) } } }) }, header: { LabeledView(label: "Items", view: { Button("", systemImage: "plus", action: {}) }) }) Section(content: { ForEach(modifiers) { modifier in LabeledText(label: modifier.timestamp.formatAsString(), value: .currency(modifier.value)) } .onDelete(perform: { indexSet in indexSet.forEach { index in context.delete(modifiers[index]) } }) }, header: { LabeledView(label: "Modifiers", view: { Button("", systemImage: "plus", action: {}) }) }) Section(content: { ForEach(transactions) { transaction in LabeledText(label: transaction.note, value: .int(transaction.getModifierCount())) } .onDelete(perform: { indexSet in withAnimation { for index in indexSet { context.delete(transactions[index]) } } }) }, header: { LabeledView(label: "Transactions", view: { Button("", systemImage: "plus", action: {addTransaction.toggle()}) }) }) } .navigationTitle("Testing") .sheet(isPresented: $addTransaction, content: { TransactionEditor() }) } } } } Here's the scenario. Create a transaction with 1 item. That item will contain 1 modifier. ContentView will display Items, Modifiers, and Transactions. For Item, it will display the date and how many modifiers it has. Modifier will display the date and its value. Transactions will display a date and how many modifiers are contained inside of its items. When I delete a modifier, in this case the only one that exist, I should see the count update to 0 for both the Item and the Transaction. This is not happening unless I close the application and reopen it. If I do that, it's updated to 0. I tried to add an ID variable to the view and change it to force a refresh, but it's not updating. This issue also seems to be only with this many to many relationship. Previously, I only had the Transaction and Item models. Deleting an Item would correctly update Transaction, but that was a one to many relationship. I would like for Modifier to have a many to many relationship with Items, so they can be reused. Why is deleting a modifier not updating the items correctly? Why is this not refreshing the view? How can I resolve this issue?
Posted
by
Post not yet marked as solved
1 Replies
121 Views
Hi everyone, I'm trying to make use of a background actor in my SwiftUI project. Inserting data works with the ModelContainer's mainContext. Another context in a ModelActor, however, fails to write into the same database. I verify the results by opening the SQLite file on the file system. While the mainContext.insert call does indeed insert a row into the table, the ModelActor's context fails to do so. There is no error or message received in the ModelActor. The property autosaveEnabled is set to true. I wrote a sample project to reproduce the issue in isolation. It consists of a single source file that introduces the Model ToDo, the ToDoView, initializes the ModelContainer and ModelActor. Please find the source code below. Is there any mistake in my approach? import SwiftUI import SwiftData @Model final class ToDo { let title: String init(title: String) { self.title = title } } @main struct testSwiftDataApp: App { @State var modelContainer: ModelContainer @State var backgroundData: BackgroundDataActor init() { let modelContainer: ModelContainer = try! ModelContainer(for: ToDo.self) self.modelContainer = modelContainer self.backgroundData = BackgroundDataActor( modelContainer: modelContainer ) } var body: some Scene { WindowGroup { ToDoView(backgroundData: self.backgroundData) .modelContainer(modelContainer) } } } struct ToDoView: View { @Environment(\.modelContext) var modelContext @Query var todos: [ToDo] let backgroundData: BackgroundDataActor var modelContainer: ModelContainer { self.modelContext.container } var body: some View { VStack { Text("Add ToDo") TextField( "", text: .constant( "URL to database: " + "\(self.modelContainer.configurations.first!.url)" ) ) // This action will be invoked on the ModelActor's context Button { Task { let todo = ToDo(title: "Step 1") await self.backgroundData.store( id: todo.persistentModelID ) } } label: { Text("Create ToDo in background") } // This action will be invoked on the mainContext Button { Task { let todo = ToDo(title: "Step 2") self.modelContainer.mainContext.insert(todo) } } label: { Text("Create ToDo in foreground") } // Show the query results VStack { Text("Available ToDos") ForEach(self.todos) { Text($0.title) } } } } } @ModelActor actor BackgroundDataActor: ModelActor { func store(id: PersistentIdentifier) { print("Trying to save") print("Is auto save enabled: \(self.modelContext.autosaveEnabled)") if let dbo = self[id, as: ToDo.self] { self.modelContext.insert(dbo) try! self.modelContext.save() print("Saved into database") } } }
Posted
by
Post not yet marked as solved
0 Replies
119 Views
I have a TabView which consists of a few different tabs. One of which does an @Query to retrieve an array of Transaction models. These are then displayed in a list using a ForEach. struct TransactionsTab: View { @Query private var transactions: [Transaction] ... other code Section(content: { ForEach(transactions) { transaction in transaction.getListItem() } }, header: { LabeledView(label: "Recent Transactions", view: { ListButton(mode: .link(destination: { ListView(list: transactions) .navigationTitle("All Transactions") })) }) }) Transaction contains a different model called TransactionItem and that has a variable called amount. That amount variable is used in the getListItem() function to show how much the total transaction was in the list item. The issue is that I can delete a Transaction and the ForEach will update to reflect that. However, if I delete an TransactionItem separately, that getListItem() will not show that it's been deleted. The total amount shown will still be as if the TransactionItem was never deleted. It will only update when the app is closed and reopened. Below is the code that's ran when deleting a model, in this case a TransactionItem. // Deletes a single item private func delete() { deleteWarning = false if let item = itemToDelete { // If last item is being delete, dismiss the view if list.count == 1 { dismissView() } context.delete(item) context.saveContext() itemToDelete = nil } mode = .view } I would think that deleting the model and having it save will cause the transaction query to update. What's going on here to cause it to not update? By the way, saveContext() just calls the ModelContext save function. extension ModelContext { func saveContext() { do { try self.save() } catch { print("Could not save context: \(error.localizedDescription)") } } }
Posted
by
Post not yet marked as solved
0 Replies
138 Views
Hello, I developed an application that uses iBeacons to create events, however when the app is in the terminated state I notice that part of my code is activated but the rest of the process is not activated ex : ranging beacon and notification. Is there a way to completely wake up my app when it is in terminated state or at least send a notification to the user to inform them that the app must be opened to put it back in background state so that the app working correctly?
Posted
by