Post

Replies

Boosts

Views

Activity

wrong value on the first buttonClick
When I run this code, and click on one of both 'currentZin' in the first screen that comes up with the view WordView, I see the content of the .preview value I used to initialize currentVerse (Verse= .preview) and not the values of the currentVerse that is in the Button action. When I leave the WordView-sheet and click again the WordView shows the good result. I looks that on the first click the currentVerse = verse in the Button is not executed. If Ido not initialize it, it has a nil value. Can Anyone explain what happens and how to solve it. struct HymnVerses: View { var hymn:Hymn @State private var currentZin: Int = 2 @State private var isLatin: Bool = true @State private var isMasked: Bool = false @State private var isTranslation: Bool = true @State private var currentSentence: String = "" @State private var showWordView: Bool = false @State private var currentVerse: Verse = .preview // Deze calculated property wordt op voorhand berekend. // Hierdoor blijft de referentie naar het origineel bestaan // wanneer ik currentVerse bereken. Daarvoor geraakte ik ze altijd kwijt. private var filteredVerses: [Verse] { hymn.verses.filter { $0.zin <= currentZin } } var body: some View { List { ForEach(filteredVerses) { verse in VStack(alignment: .leading) { Button { currentVerse = verse showWordView = true } label: { Text("\(verse.zin). \(currentSentence(for: verse))") .font(.headline) } } } .onAppear { currentVerse = filteredVerses.first! } }.sheet(isPresented: $showWordView, content: { WordView(vers: currentVerse, showWordView: $showWordView) }) .toolbar { ToolbarItem(placement: .bottomBar) { Button(isLatin ? "Dutch" : "Latin") { isLatin.toggle() } } ToolbarItem(placement: .bottomBar) { Button(isMasked ? "Unmask" : "Mask") { isMasked.toggle() } } ToolbarItem(placement: .bottomBar) { Button("Restart") { currentZin = 1 } } ToolbarItem(placement: .bottomBar) { Button("Next") { if currentZin < hymn.verses.count { currentZin += 1 } } } } } func maskLetters(in sentence: String, with mask: Character = "*") -> String { return sentence.map { char in if char.isLetter { return String(mask) } else { return String(char) } }.joined() } private func currentSentence(for verse: Verse) -> String { var temp: String { return isLatin ? verse.latijn : verse.nederlands } if isMasked { return maskLetters(in: temp) } else { return temp } } } #Preview { /// the navigationStack is nodig omdat anders de toolbar niet zichtbaar is met #Preview NavigationStack { let allTexts = AllTexts() HymnVerses(hymn: .preview).environment(allTexts) } }
3
0
204
Jan ’25
Filter a list of Item objects on a related Product Object passed as a Bindable
I'm currently developing a SwiftUI application that utilizes SwiftData for data management. I am facing a challenge when trying to filter a query. Specifically, I want to filter a list of Item objects to match a Product instance that is passed to my View. error : Instance member 'product' cannot be used on type 'MainItemListEncap'; did you mean to use a value of this type instead The view // // 311.1.1. MainRefToItem.swift // ComparePrice // // Created by Herman VAN CAUWELAERT on 11/12/2024. // import SwiftUI import SwiftData struct MainItemListEncap: View { @Bindable var product: Product @Query( filter: #Predicate { item in item.productGroup == product }, sort: [SortDescriptor(\Item.name)] ) var items: [Item] @Environment(\.modelContext) var modelContext var body: some View { ForEach(items) { item in VStack(alignment: .leading) { Text(item.name) Text(item.description) } } } } the product class. import SwiftData import Foundation @Model final class Product: CustomStringConvertible, CustomDebugStringConvertible { @Attribute(.unique) var productName: String var productDescription: String var outputCurrency: String // Gebruik een `String` als opslag voor `outputSystem` var outputSystemRawValue: String = MeasurementSystem.metric.rawValue // Computed property om `MeasurementSystem` te gebruiken var outputSystem: MeasurementSystem { get { MeasurementSystem(rawValue: outputSystemRawValue) } set { outputSystemRawValue = newValue.rawValue } } // er zijn verschillend item versies voor een product // als er een hoofdproduct gedelete wordt, dan zullen alle onderliggende items ook gedelete worden @Relationship(deleteRule: .cascade, inverse: \Item.productGroup) var refToItems = [Item]() init(productName: String = "", productDescription: String = "what is this product", outputCurrency: String = "EUR", outputSystem: MeasurementSystem = MeasurementSystem.metric) { self.productName = productName self.productDescription = productDescription self.outputCurrency = outputCurrency self.outputSystem = outputSystem } } the item class import Foundation import SwiftData @Model final class Item: CustomStringConvertible, CustomDebugStringConvertible { var timestamp: Date @Attribute(.unique) var name: String var productGroup: Product? var shop: String //TODO: becomes Shop var price: Double var currency: String var quantity: Double var unit: String //TODO: becomes Unit var isShown : Bool var minimumQuantity: String var rateStr: String { conversionRate != nil ? " (rate: \(ValueFormatter.shared.format(conversionRate!)))" : "" } init(timestamp: Date = Date() , name: String , shop: String = "Colruyt" , price:Double = 1.00 , currency: String = "EUR" , quantity: Double = 1.0 , unit: String = "g" , isShown:Bool = true , conversionRate: Decimal? = 1 , minimumQuantity: String = "1" ) { self.timestamp = timestamp self.name = name self.shop = shop self.price = price self.currency = currency self.quantity = quantity self.unit = unit self.isShown = isShown self.conversionRate = conversionRate self.minimumQuantity = minimumQuantity } }
2
0
358
Dec ’24