I'm building a UI with SwiftUI, and I have an array that I use to build a List
element. Now I want to sort that list based on a @Published
variable coming from an @EnvironmentObject
.
I tried getting the array already sorted, passing in the environment object to the sorting method:
List(getArraySorted(environmentObject)) { item in
//do stuff with item
}
This will compile, but the list will not update if environmentObject
changes. I also tried passing in environmentObject.variableToBaseSortOn
but to no avail.
I tried sorting the array inline in Swift UI:
List(array.sorted(by: { (lhs, rhs) -> Bool in
// do sorting based on self.environmentObject
})) { item in
// do stuff with item
}
This will compile, but crash:
Fatal error: No ObservableObject of type EnvironmentObjectClass found.
A View.environmentObject(_:) for EnvironmentObjectClass may be missing as an ancestor of this view.
The hint in the crash is incorrect, environmentObject
is set and self.environmentObject
is set to the correct object.
Your best approach is probably to sort the list within ObservableObject
each time the data changes using a property observer, then manually informing the ObservableObject
publisher of the change (rather than using @Published
, so the unsorted array is not briefly published between changes.)
It's not a good idea to do the sorting directly in the body
of the View
because that block may be called many, many times as SwiftUI renders it (this is transparent to us as developers). I suspect that may be a reason that Approach 2 is not working.
For example:
import Combine
class SomeObject: ObservableObject {
// or whatever data type you need...
var array: [String] {
didSet {
array.sort(by: { (lhs, rhs) -> Bool in
// do sorting based on self.environmentObject
})
objectWillChange.send()
}
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With