Reputation: 20136
I have some items and show an item count on the view. I have a toggle that reduces what is shown in the count/item list. The item count doesn't update when I use the toggle. What am I missing here? Cut down / mock example for conciseness.
struct SampleView: View {
@State var items:[Item]
@State var easyMode:Bool = false
@State var filtered:[Item] = []
init(...) {
// Fill items and filtered array
}
var body: some View {
Toggle(isOn: $easyMode, label:{
Text("Easy mode")
})
.onChange(of: self.easyMode, perform: { value in
filtered = filterItems()
// ^^ This is running but not
// updating stuff
})
// This text field does not update when filter changes
Text(String(filtered.count) + " items")
}
}
I tried having the filterItems generate a text string in i.e. @State var countLabel:String
and update the text, but there is a background thread issue. So I assume there is some weirdness where the filterItems isn't doing anything because its on a separate thread. What am I missing? Thanks!!
Upvotes: 1
Views: 1085
Reputation: 11426
I have just take your code and make it compilable.
struct SOTest: View {
@State var items:[String]
@State var easyMode:Bool = false
@State var filtered: [String]
init() {
let tmp = ["1","2_","3","4_","5_","6"]
self.items = tmp
self.filtered = tmp.filterStrings()
}
var body: some View {
Toggle(isOn: $easyMode, label:{
Text("Easy mode")
})
.onChange(of: self.easyMode, perform: { value in
if value {
filtered = items.filterStrings()
} else {
filtered = items
}
})
Text(String(filtered.count) + " items")
}
}
extension Array where Element == String {
func filterStrings() -> [String] {
self.filter{ $0.contains("_") }
}
}
and all works perfectly.
Try to check my answer here, maybe you will find solution of your hidden issue: SwiftUI: Forcing an Update
and.... by the way, here is more simple way to do the same:
struct SOTest: View {
@State var items:[String]
@State var easyMode:Bool = false
@State var filtered: [String]
init() {
let tmp = ["1","2_","3","4_","5_","6"]
self.items = tmp
self.filtered = tmp.filterStrings()
}
var body: some View {
Toggle(isOn: $easyMode, label:{
Text("Easy mode")
})
if easyMode {
Text(String(filtered.count) + " items")
}
else {
Text(String(items.count) + " items")
}
}
}
Upvotes: 1
Reputation: 36304
you could try this:
.onChange(of: self.easyMode) { value in
DispatchQueue.main.async {
filtered = filterItems()
}
}
Upvotes: 1