I attempted to create a SortDescriptor using a method in enum to sort various different models in SwiftUI lists. But it causes crashes in Xcodes previews but not in the simulator, and I don't know why. Maybe someone could suggest changes.
extension Item:ListSorting {} //List sorting is a protocol given to various Models
enum ListSortingStyle<T>:String,CaseIterable where T:ListSorting {
case alphabetical = "A…Z"
case alphabeticalReverse = "Z…A"
case createDate = "Newest"
case createDateReverse = "Oldest"
case editDate = "Latest Edit"
case editDateReverse = "Oldest Edit"
/// Returns a SortDescriptor matching the enumeration
func sortDescriptor() -> SortDescriptor<T> {
switch self {
case .alphabetical:
SortDescriptor<T>(\.name, comparator: .localized, order: .forward)
case .alphabeticalReverse:
SortDescriptor<T>(\.name, comparator: .localized, order: .reverse)
case .createDate:
SortDescriptor<T>(\.creationDate, order: .forward)
case .createDateReverse:
SortDescriptor<T>(\.creationDate, order: .reverse)
case .editDate:
SortDescriptor<T>(\.editDate, order: .forward)
case .editDateReverse:
SortDescriptor<T>(\.editDate, order: .reverse)
}
}
}
Which is used in
struct ItemsList: View {
@Environment(\.modelContext) private var modelContext
@Query private var items:[Item] = []
init(sortStyle:ListSortingStyle<Item> = .alphabetical) {
let sortDescriptor = SortDescriptor<Item>(\.name, comparator: .localized, order: .forward) //(1) This works in preview & simulator
//OR
let sortDescriptor2 = sortStyle.sortDescriptor() //(2) This crashes in a preview when used in a fetch not in the iOS simulator
print(sortDescriptor,sortDescriptor2)
let descriptor = FetchDescriptor<Item>(sortBy:[sortDescriptor2])
self._items = Query(descriptor)
}
var body: some View {
...
}
}
As far as I can see both methods create a SortDiscriptor. If I print the sortDescriptor variable in they look almost identical:
//1
SortDescriptor<Item>(
order: Foundation.SortOrder.forward,
keyString: nil,
comparison: Foundation.SortDescriptor<MyApp.Item>.AllowedComparison.comparableString(
(extension in Foundation):Swift.String.StandardComparator(options: __C.NSStringCompareOptions(rawValue: 0),
isLocalized: true,
order: Foundation.SortOrder.forward),
\Item. <computed 0x0000000340213b18 (String)>)
)
//2
SortDescriptor<Item>(
order: Foundation.SortOrder.forward,
keyString: nil,
comparison: Foundation.SortDescriptor<MyApp.Item>.AllowedComparison.comparableString(
(extension in Foundation):Swift.String.StandardComparator(options: __C.NSStringCompareOptions(rawValue: 0),
isLocalized: true,
order: Foundation.SortOrder.forward),
\Item.<computed 0x0000000340022174 (String)>)
)
But the one created with the generic method on the enum crashes with the error message:
CrashReportError: Fatal Error in DataUtilities.swift
MyApp crashed due to fatalError in DataUtilities.swift at line 64.
Couldn't find \Item.<computed 0x0000000340022174 (String)> on Item with fields [SwiftData.Schema.PropertyMetadata ...