Reputation: 485
I have a ScooterReservationView class in SwiftUI:
...
@State var extensionIDs: [Int] = []
var body: some View {
...
List(scooterExtensionVM.extensions, id: \.self) { scooterExtension in
ScooterExtensionRow(_extension: scooterExtension, extensionIDs: self.$extensionIDs)
}
...
The scooterExtensionVM.extensions array gets its value from an API request, the extensions are totally dynamic based on the backend API. Then I have the ScooterExtensionRow struct:
struct ScooterExtensionRow: View {
@EnvironmentObject var appState: AppState
@Binding var extensionIDs: [Int]
var scooterExtension: ScooterExtension
@State var isOn: Bool = true
init(_extension: ScooterExtension, extensionIDs: Binding<[Int]>) {
self.scooterExtension = _extension
self._extensionIDs = extensionIDs
}
var body: some View {
HStack {
Toggle(isOn: self.$isOn) {
Text(scooterExtension.name)
}
.padding()
}
}
}
My goal is to update extensionIDs array when the Toggle inside any of the ScooterExtensionRow view has changed. If any of the Toggle is switch on, I need to add the ScooterExtension's extension ID to that array, if its off, I need to remove the id from the array. This needs me for an API request later. (I need to collect all of the IDs of the enabled/toggled extensions)
The problem is: I cannot see in the docs any kind of callback action for the Toggle, where I can append/remove the value to/from the array, but maybe a callback is not the best way to do it in that Great SwiftUI World.
Can anyone help what is the best way to achieve this?
Upvotes: 3
Views: 888
Reputation: 257703
Assuming ScooterExtension
has a property id
, it can be done as follows:
Toggle(isOn: Binding<Bool>(get:{ self.isOn },
set: {
self.isOn = $0
if $0 {
self.extensionIDs.append(self.scooterExtension.id)
} else {
self.extensionIDs = self.extensionIDs.filter { $0 != self.scooterExtension.id }
}
})) {
Text(scooterExtension.name)
}
Upvotes: 3
Reputation: 424
Ah, I see what you are saying in your comment. How about a new container type for the ids. Something like
class ExtensionID: Identifiable, ObservableObject {
let id: Int
var isOn: Bool = true
init(id: Int) {
self.id = id
}
}
Then you can bind the Toggle to the isOn
property and conditionally display the ScooterExtensionRow (or whatever other changes you need based on a given id being off instead of actually missing from the array) based on this as well.
Does this make any sense?
Upvotes: 0