I did use print statements and de debugger before, but not the .onChange method.
When I add the .onChange to see what happens, the result is good, but when I put it in comment, then the result is wrong. I changed the program like this.
I will add to screenshots one with .onChange in my code and one with the result when I put .onChange in comment.
This is my code now :
code-block
//
// HymnVerses.swift
// Tridenti
//
// Created by Herman VAN CAUWELAERT on 08/01/2025.
//
import SwiftUI
struct HymnVerses: View {
var hymn:Hymn
@State private var currentZin: Int = 1
@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 {
handleVerseSelection(verse)
} label: {
Text("\(verse.zin). \(currentSentence(for: verse))")
.font(.headline)
}
}
} .onAppear {
print ("Start .onAppear")
currentVerse = filteredVerses.first!
print ("End .onAppear")
}
}
.onChange(of: currentVerse) { oldValue, newValue in
print("currentVerse changed:")
print("Van: \(oldValue.latijn)")
print("Naar: \(newValue.latijn)")
}
.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
}
}
}
}
}
private func handleVerseSelection(_ verse: Verse) {
currentVerse = verse
print("\(currentVerse.latijn)")
showWordView = true
}
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)
}
}