I’m trying to sort a list using Picker inside a Menu as in the image
the picker is working and sorting is working, the missing part is sorting order
the goal behavior:
when user select a sort field and the sort order will be ASC, but when he select the same field again sort order should be DES.
how can I detect if the user selected the same field again in picker? or is there a better approach.
thank you
here is my example code
struct Book: Identifiable {
let id = UUID()
let title, author: String
let sales: Int
}
enum SortField: String, CaseIterable {
case title, author, sales
}
struct ContentView: View {
@State private var items: [Book] = [
.init(title: "Da Vinci Code,The", author: "Brown, Dan", sales: 5094805),
.init(title: "Harry Potter and the Deathly Hallows", author: "Rowling, J.K.", sales: 4475152),
.init(title: "Angels and Demons", author: "Brown, Dan", sales: 3193946),
.init(title: "One Day", author: "Nicholls, David", sales: 1616068),
.init(title: "Billy Connolly", author: "Stephenson, Pamela", sales: 1231957),
]
@State private var selectedSortField: SortField = .title
@State private var ascending: Bool = false
var body: some View {
NavigationView {
Form {
ForEach(items) { item in
HStack {
VStack(alignment: .leading) {
Text(item.title)
.font(.headline)
Text(item.author)
}
Spacer()
Text("(item.sales)")
.font(.caption)
}
}
}
.toolbar {
Menu {
Picker(selection: $selectedSortField, label: Text("Sorting")) {
ForEach(SortField.allCases, id: .self) { field in
HStack {
Text(field.rawValue)
if selectedSortField == field {
Image(systemName: ascending ? "arrow.up" : "arrow.down")
}
}
}
}
.onChange(of: selectedSortField) { _ in sort() }
} label: {
Label("Menu", systemImage: "ellipsis.circle")
}
}
}
}
private func sort() {
switch selectedSortField {
case .title: items.sort { ascending ? $0.title < $1.title : $0.title > $1.title }
case .author: items.sort { ascending ? $0.author < $1.author : $0.author > $1.author }
case .sales: items.sort { ascending ? $0.sales < $1.sales : $0.sales > $1.sales }
}
}
}
2
Answers
this is another solution to this problem
A way to achieve this would be to include the
ascending
flag in theSortField
cases. e.g.