Post

Replies

Boosts

Views

Activity

Reply to SwiftData Equivalent of @SectionedFetchRequest
So I finally just decided to create my own "Grouped" var called groupedCustomers which groups the customers (all or just filtered results) by the first letter of their name, sorts the customers alphabetically in each group and then finally sorts the entire group alphabetically: private var groupedCustomers: [GroupedCustomer] { var groupedCusts : [String: [SD_Customer]] var sortedCusts: [GroupedCustomer] = [] var retVal: [GroupedCustomer] = [] groupedCusts = Dictionary(grouping: (searchText.isEmpty ? customers : customers.filter {$0.custName.lowercased().contains(searchText.lowercased())}), by: \.firstLetterOfCustName) sortedCusts = groupedCusts.map { (arg) -> GroupedCustomer in let (key, values) = arg return GroupedCustomer(id: key, customers: values.sorted {$0.custName < $1.custName}) } retVal = sortedCusts.sorted { $0.id < $1.id } return retVal } Full View: import SwiftUI import SwiftData struct CustomerMasterView: View { //data @Environment(\.modelContext) private var modelContext @Query(sort: \.custName, order: .forward, animation: .spring) private var customers: [SD_Customer] @State private var selectedCustomer: SD_Customer? //state @State private var searchText: String = "" //calculated values private var groupedCustomers: [GroupedCustomer] { var groupedCusts : [String: [SD_Customer]] var sortedCusts: [GroupedCustomer] = [] var retVal: [GroupedCustomer] = [] groupedCusts = Dictionary(grouping: (searchText.isEmpty ? customers : customers.filter {$0.custName.lowercased().contains(searchText.lowercased())}), by: \.firstLetterOfCustName) sortedCusts = groupedCusts.map { (arg) -> GroupedCustomer in let (key, values) = arg return GroupedCustomer(id: key, customers: values.sorted {$0.custName < $1.custName}) } retVal = sortedCusts.sorted { $0.id < $1.id } return retVal } //body var body: some View { NavigationSplitView { List(groupedCustomers, id: \.id, selection: $selectedCustomer) { header in Section { ForEach(header, id: \.self) {customer in CustomerListCellView(customer: customer) } } header: { Text("\(header.id) - \(header.customers.count)") } } .listStyle(PlainListStyle()) .searchable(text: $searchText, placement: .navigationBarDrawer(displayMode: .always)) .disableAutocorrection(true) .navigationTitle(Text("CUSTOMERS")) //.navigationBarItems(trailing: menuButton) } detail: { if let cust = self.selectedCustomer { CustomerDetailView(customer: cust) } else { ContentUnavailableView("Nothing To See Here", systemImage: "eyes", description: Text("Select a customer from the list to view thier details.")) } } } } struct GroupedCustomer: Identifiable, RandomAccessCollection { typealias Element = SD_Customer typealias Index = Int var id: String var customers: [SD_Customer] init(id: String, customers: [SD_Customer]) { self.id = id self.customers = customers } var startIndex: Int { return customers.startIndex } var endIndex: Int { return customers.endIndex } subscript(position: Int) -> SD_Customer { return customers[position] } func index(after i: Int) -> Int { return customers.index(after: i) } } Hope this helps. And if you find any errors or improvements to my code, please let me know.
Jun ’23