I have an application with multiple views (three levels). The single source of truth, a data structure, is passed, from parent to child, using an @EnvironmentObject.
Now, in the child view, as soon as I touch any control like a Toggle (bound to a boolean element of the passed data structure) the application switch immediately to the parent View.
What I am doing wrong?
Thanks
Parent View code:
//
// TestView.swift
// swiftui-test
import SwiftUI
let freqNames = ["minutes": "minute", "hourly": "hour", "daily":"day", "weekly":"week", "monthly":"month"]
struct WateringView: View {
@EnvironmentObject var hacData: HACModelData
@State private var editMode = EditMode.inactive
var body: some View {
let _ = print(hacData)
VStack {
List {
Section(header: Text("Plant activation schedule")) {
Toggle(isOn: $hacData.hac.watering.plantActive) {
Text("Plant active")
}
DatePicker("Start date", selection: $hacData.hac.watering.scheduling.startDTime)
.environment(\.locale, Locale(identifier: "en_IT"))
Picker("Repeat frequency", selection: $hacData.hac.watering.scheduling.repeatFreq) {
ForEach(HAC.WateringControl.ScheduleData.RepeatFrequency.allCases) { repfreq in
Text(repfreq.id)
}
}
.pickerStyle(MenuPickerStyle())
let pfix = hacData.hac.watering.scheduling.repeatCount > 1 ? "s":""
Stepper("Repeat every \($hacData.hac.watering.scheduling.repeatCount) \(freqNames[$hacData.hac.watering.scheduling.repeatFreq]!)\(pfix)",
value: $hacData.hac.watering.scheduling.repeatCount, in: 1...60, step: 1)
}
Section(header: Text("Zones")) {
ForEach(hacData.hac.watering.zones, id: \.id) { zone in
NavigationLink(destination: ZoneView(zone: zone)) {
ZoneItemView(zone: zone)
}
}
.onMove(perform: onMove)
}
}
.navigationBarTitle(Text("Watering setup"))
.navigationBarItems(leading: EditButton())
.environment(\.editMode, $editMode)
}
}
private func onMove(source: IndexSet, destination: Int) {
hacData.hac.watering.zones.move(fromOffsets: source, toOffset: destination)
}
}
struct WateringView_Previews: PreviewProvider {
static let hacData = HACModelData()
static var previews: some View {
WateringView()
}
}
Child View code:
//
// ZoneView.swift
// swiftui-test
//
// Created by Franco Fiorese on 15/08/21.
//
import SwiftUI
struct ZoneView: View {
@EnvironmentObject var hacData: HACModelData
var zone: HAC.WateringControl.Zone
var zoneIndex: Int {
hacData.hac.watering.zones.firstIndex(where: { $0.id == zone.id })!
}
var footer1: some View {
Text("Enable or Disable the Zone during the scheduled watering cycles")
}
var footer2: some View {
Text("Activate zone watering immediately")
}
var footer3: some View {
Text("Set the zone watering cycle duration in minutes")
}
var body: some View {
let _ = print("\(zone.id) -> \(zone)")
let _ = Self._printChanges()
VStack {
List {
Section(/* header: Text("Current state"), */ footer: footer1) {
Toggle(isOn: $hacData.hac.watering.zones[zoneIndex].isEnabled) {
Text("Enable during scheduling")
}
}
Section(/* header: Text("Activation"), */ footer: footer2) {
Toggle(isOn: $hacData.hac.watering.zones[zoneIndex].isActive) {
Text("Activate")
}
}
Section(header: Text("Duration"), footer: footer3) {
HStack {
Slider(value: $hacData.hac.watering.zones[zoneIndex].duration, in: 0...60, step: 1)
.accentColor(Color.green)
Text("\(Int(zone.duration))")
}
}
}
.navigationBarTitle(Text("Zone setup"))
Spacer()
}
}
}
struct ZoneView_Previews: PreviewProvider {
static let hacData = HACModelData()
static var previews: some View {
ZoneView(zone: hacData.hac.watering.zones[0])
.environmentObject(hacData)
}
}