I am struggling with sorting array in SwiftUI. I am looping through my array in ForEach
using indices and I want to sort the whole array. I have objects that can't be Hashable
because of CGSize
value that's why I can't use enumerated()
. After hours of trying I still don't know how to achieve sorted array.
Here is code for object:
struct Object: Identifiable {
var id = UUID()
var position: CGPoint = .zero
var num: Int
}
and ContentView:
struct ContentView: View {
@State var objects = [
Object(num: 3),
Object(num: 5),
Object(num: 6),
Object(num: 2),
Object(num: 4),
Object(num: 1)
]
var body: some View {
VStack {
ForEach(objects.sorted(by: {$0.num > $1.num}).indices, id:\.self) { i in
Text("\(objects[i].num)")
}
}
.padding()
}
}
CodePudding user response:
Your code does not produce the expected results because you use the indices of the sorted array as subscripts to the original array: Both
objects.indices
objects.sorted(by: {$0.num > $1.num}).indices
are the range 0 ..< objects.count
, sorting the array has no effect. And therefore does
Text("\(objects[i].num)")
display the objects in their original order.
A quick fix would be to sort the indices instead:
ForEach(objects.indices.sorted(by: {objects[$0].num > objects[$1].num}), id:\.self) { i in
Text("\(objects[i].num)")
}
But if you add Hashable
conformance to your custom type
extension Object : Hashable {
func hash(into hasher: inout Hasher) {
hasher.combine(id)
hasher.combine(position.x)
hasher.combine(position.y)
hasher.combine(num)
}
}
then displaying the sorted objects becomes as simple as
ForEach(objects.sorted(by: { $0.num > $1.num})) { obj in
Text("\(obj.num)")
}