это воссоздание проблемы, с которой я столкнулся в своем коде SwiftUI. Предположим, у меня есть список устройств, и для каждого я имею некоторую информацию о подключении (включено или нет).
Используя classi c Список в SwiftUI, для каждого устройства будет отображаться DeviceView. Для удобства я хочу добавить пару стрелок вверху для переключения между устройствами, не возвращаясь обратно в список каждый раз (чтобы понять, как приложение Почта в iOS). Таким образом, вместо вызова DeviceView из списка, я прежде вызываю MotherDeviceView, в котором хранится информация о текущем устройстве. Когда я нажимаю на стрелки вверху, MotherDeviceView снова вызывает DeviceView, и представление обновляется.
struct Device: Identifiable {
var id = Int()
var deviceName = String()
var isWifiOn = Bool()
var isCellularOn = Bool()
var isBluetoothOn = Bool()
}
let devices: [Device] = [
Device(id: 0, deviceName: "iPhone", isWifiOn: true, isCellularOn: false, isBluetoothOn: true),
Device(id: 1, deviceName: "iPod", isWifiOn: false, isCellularOn: false, isBluetoothOn: true),
Device(id: 2, deviceName: "iPad", isWifiOn: false, isCellularOn: true, isBluetoothOn: false)
]
// main view, with list of devices
struct DeviceTab: View {
var body: some View {
NavigationView {
List(devices) { device in
NavigationLink(destination: MotherDeviceView(device: device)){
Text(device.deviceName)
}
}.navigationBarTitle(Text("Devices"))
}
}
}
// the list call this view and pass the device to DeviceView.
// Using this view is possible to go to the other device using the arrows on the top
// without returning to the list
struct MotherDeviceView: View {
@State var device: Device
var body: some View {
VStack{
DeviceView(device: $device)
}
.navigationBarItems(trailing: arrows)
}
private var arrows: some View {
HStack{
Button(action: { self.previous() },
label: { Image(systemName: "chevron.up") } )
.padding(.horizontal, 10)
Button(action: { self.next() },
label: { Image(systemName: "chevron.down") } )
}
}
func previous() {
if device.id == 0 { return }
device = devices[device.id - 1]
}
func next() {
if device.id == 2 { return }
device = devices[device.id + 1]
}
}
// DeviceView
struct DeviceView: View {
@Binding var device: Device
var body: some View {
VStack{
Spacer()
Text("This is the device number: " + String(device.id))
Spacer()
ToggleSection(dev: $device)
Spacer()
}.navigationBarTitle(device.deviceName)
}
}
// Toggle part of DeviceView
struct ToggleSection: View {
@Binding var dev: Device
@State var toggleOn: [Bool] = [false, false, false]
var body: some View {
VStack{
Text(dev.deviceName)
.fontWeight(.bold)
Toggle(isOn: $toggleOn[0], label: { Text("Wifi") } )
.padding()
Toggle(isOn: $toggleOn[1], label: { Text("Cellular") } )
.padding()
Toggle(isOn: $toggleOn[2], label: { Text("Bluetooth") } )
.padding()
}
.onAppear{ self.initialConfigToggle() }
// with onAppear is okay, but when I use the top arrows, this section does not update
}
private func initialConfigToggle() {
self.toggleOn[0] = self.dev.isWifiOn
self.toggleOn[1] = self.dev.isCellularOn
self.toggleOn[2] = self.dev.isBluetoothOn
}
}
Но в DeviceView есть раздел ToggleSection, который не будет обновляться, и я не знаю, как решить эту проблему. Может быть, принудительное обновление? Но я не думаю, что это правильный ответ (и, тем не менее, я даже не знаю, как заставить обновление).
Я думаю, что если в ToggleSection есть @Binding, а не @State, может быть, это правильно ответьте, но это не работает. Этот пример будет работать (за исключением того, что переключатель не обновлен)
Заранее спасибо!