Reputation: 2836
I have found almost the perfect code for my needs. But there is one problem:
I would like to use toggles in each row instead of buttons.
Original code posted by @kontiki here: SwiftUI hide list item from list item view
import SwiftUI
struct Item: Identifiable {
let id = UUID()
var isComplete: Bool = false
}
class Model: ObservableObject {
@Published var isOn: Bool = false
@Published var arr = [Item(isComplete: true), Item(isComplete: false), Item(isComplete: true), Item(isComplete: false), Item(isComplete: true), Item(isComplete: true)]
}
struct ContentView: View {
@ObservedObject var model = Model()
var body: some View {
List {
Toggle(isOn: $model.isOn) { Text("Toggle") }
ForEach(self.model.arr.filter { model.isOn ? true : $0.isComplete }) { item in
Row(item: item, model: self.model)
}
}
}
}
struct Row: View {
let item: Item
@ObservedObject var model: Model
var body: some View {
HStack {
Button(action: {
if let idx = self.model.arr.firstIndex(where: { $0.id == self.item.id }) {
self.model.arr[idx].isComplete.toggle()
self.model.isOn = false
}
}) {
Text("Button")
}
Text(item.isComplete ? "Complete" : "Not complete")
}
}
}
Instead of button I have tried to use toggle like this:
Toggle(isOn: $item.isComplete) {
Text("Done")
}
There is this if statement inside button that I don't understand. I have tried to take this let idx declaration outside of button too to make it easier for using toggle (as I don't know how to make such complicated toggle) but this also failed.
Upvotes: 2
Views: 2272
Reputation: 257493
Note: There is known issue with Toggle control update in List. Please be aware. The details are in Problems with layout of some rows in SwiftUI list topic.
Here is possible approach. Modified lines are marked in comments.
import SwiftUI
struct Item: Identifiable, Equatable { // <<
let id = UUID()
var isComplete: Bool = false
}
class Model: ObservableObject {
@Published var isOn: Bool = false
@Published var arr = [Item(isComplete: true), Item(isComplete: false), Item(isComplete: true), Item(isComplete: false), Item(isComplete: true), Item(isComplete: true)]
}
struct ContentView: View {
@ObservedObject var model = Model()
var body: some View {
List {
Toggle(isOn: $model.isOn) { Text("Toggle") }
ForEach(self.model.arr.filter { model.isOn ? true : $0.isComplete }) { item in
Row(item: self.$model.arr[self.model.arr.firstIndex(of: item)!]) // <<
}
}
}
}
struct Row: View {
@Binding var item: Item // <<
var body: some View {
HStack {
Toggle(isOn: $item.isComplete) {
Text("Done")
}
Text(item.isComplete ? "Complete" : "Not complete")
}
}
}
Upvotes: 1