While adopting SwiftUI (and Swift Concurrency) into a macOS/AppKit application, I'm making extensive use of the .task(id:)
view modifier.
In general, this is working better than expected however I'm curious if there are design patterns I can better leverage when the number of properties that need to be "monitored" grows.
Consider the following pseudo-view whereby I want to call updateFilters
whenever one of three separate strings is changed.
struct FiltersView: View {
@State var argument1: String
@State var argument2: String
@State var argument3: String
var body: some View {
TextField($argument1)
TextField($argument2)
TextField($argument3)
}.task(id: argument1) {
await updateFilters()
}.task(id: argument2) {
await updateFilters()
}.task(id: argument3) {
await updateFilters()
}
}
Is there a better way to handle this? The best I've come up with is to nest the properties inside struct
. While that works, I now find myself creating these "dummy types" in a bunch of views whenever two or more properties need to trigger an update.
ex:
struct FiltersView: View {
struct Components: Equatable {
var argument1: String
var argument2: String
var argument3: String
}
@State var components: Components
var body: some View {
// TextField's with bindings to $components...
}.task(id: components) {
await updateFilters()
}
}
Curious if there are any cleaner ways to accomplish this because this gets a bit annoying over a lot of views and gets cumbersome when some values are passed down to child views. It also adds an entire layer of indirection who's only purpose is to trigger task(id:)
.