Reputation: 23
SeasonData is an array of objects of type Season
userData holds 2 [INT] lastUsedSeason -> which reference the last 3array positions of SeasonData that were accessed [3,1,0]
arrayPosition holds [0,1,2].
These are loaded from a file.
The display and selection of this picker works correctly. However I cannot figure out how to get the onChange to fire when changing a selection.
struct UserData: Codable {
var lastUsedSeason: [Int]
var arrayPosition: [Int]
mutating func addLastUsedSeason(index: Int) {
if (lastUsedSeason.count > 3){
lastUsedSeason.insert(index, at: 0)
lastUsedSeason.remove(at: 2)
}
}
}
@main
struct SandStats_New_App: App {
@StateObject private var modelData = ModelData()
@State private var showSeason = false
var body: some Scene {
WindowGroup {
ContentView(seasonSelected: $showSeason)
.environmentObject(modelData)
.frame(minWidth: 700, minHeight: 300, alignment: .topLeading)
.background(Color.red)
}
.commands {
SandStatCommands(addSeasonButton: $showSeason, modelData: modelData)
}
}
}
struct SandStatCommands: Commands {
var modelData : ModelData
@Binding var addSeasonButton: Bool
@State var seasonSelection: Int = 0
var body: some Commands {
CommandMenu("Season"){
Button("Add Season"){
addSeasonButton = true
}
Picker(selection: $seasonSelection, label: Text("Selected Season")){
ForEach(modelData.userData.arrayPosition, id:\.self) { index in
Text(modelData.seasons[modelData.userData.getLastUsedSeason(index1: index)].seasonName()).tag(index)
}
}.onChange(of: seasonSelection, perform: { value in
print(value)
})
Button("save Index"){
saveData(for: modelData.userData, to: "userData")
}
}
}
}
Upvotes: 2
Views: 2969
Reputation: 2575
For future users long story short:
onChange
does not gets called when 'seasonSelection' is Int
and you are trying to set String
to it.
XCode does not gives any error message/crash to figure out what's wrong.
@State var seasonSelection: String = "default" // keep this 'default' as the value you want to show on opening picker
//leaving it blank will select 0th index ""
Upvotes: 0
Reputation: 856
For seasonSelection
to work in a Picker
, add a .tag()
to Text(...)
and make sure it is of the same type as the seasonSelection
, for example (assuming index
is of type Int):
NOTE: this works for macCatalyst, for macOS only, see EDIT.
Picker(selection: $seasonSelection, label: Text("Selected Season")){
ForEach(userData.userData.lastUsedSeason, id:\.self) { index in
Text(seasonData.seasons[index].seasonName()).tag(index) // <-- here
}
}
.onChange(of: seasonSelection, perform: { _ in
seasonData.seasons[0].testPrint()
})
EDIT: sample code that shows how to use tag
with seasonSelection
in .onReceive()
on macOS only, and .onChange()
for macCatalyst.
import SwiftUI
import Combine
@main
struct TestMacApp: App {
var body: some Scene {
WindowGroup {
Text("demo").frame(width: 480.0, height: 320.0)
}
.commands {
SandStatCommands()
}
}
}
struct SandStatCommands: Commands {
@State var seasons = ["Spring","summer","autumn","winter"] // array of values
@State var seasonSelection: Int = 0 // <-- here initial selection
var body: some Commands {
CommandMenu("Season"){
Button("Add Season"){
seasons.append(String(UUID().uuidString.prefix(6))) // for demo, add a random name
}
Picker(selection: $seasonSelection, label: Text("Selected Season")){
ForEach(0..<seasons.count, id:\.self) { index in
Text(seasons[index]).tag(index) // <-- here tag
}
}
// .onChange(of: seasonSelection) { value in
// print("---> seasonSelection value: \(value)")
// }
.onReceive(Just(seasonSelection)) { value in
print("---> seasonSelection value: \(value)")
}
}
}
}
Upvotes: 1