swift - 如何使 NSSortDescriptor 的 KeyPath 通用?
问题描述
我是编程的初学者,所以如果可能的话,我会很感激初学者级别的解释。
我正在上 Paul Hudson 的 100 天 SwiftUI 课程,我们应该为泛型设置keyPath
参数。NSSortDescriptor
这是一个自定义视图的内部,可以在另一个视图中使用它来构建一个带有核心数据获取请求的列表。我希望这是有道理的。我不知道如何制作keyPath
通用的,这样当我在另一个视图中使用它时,我可以传入我想要的任何 keypath。
struct FilteredList<T: NSManagedObject, Content: View, V: Comparable>: View {
var fetchRequest: FetchRequest<T>
var singers: FetchedResults<T> { fetchRequest.wrappedValue }
var ascendingOrNot: Bool
var keyPath: KeyPath<T, V>
let content: (T) -> Content
var body: some View {
List(singers, id: \.self) { singer in
self.content(singer)
}
}
init(filterKey: String, filterValue: String, keyPath: KeyPath<T, V>, ascendingOrNot: Bool, @ViewBuilder content: @escaping (T) -> Content) {
self.keyPath = keyPath
self.ascendingOrNot = ascendingOrNot
fetchRequest = FetchRequest<T>(entity: T.entity(), sortDescriptors: [NSSortDescriptor(keyPath: keyPath, ascending: ascendingOrNot)], predicate: NSPredicate(format: "%K BEGINSWITH %@", filterKey, filterValue))
self.content = content
}
}
我尝试添加泛型类型V
并使其符合Comparable
但当我尝试在另一个视图中使用它时,我收到以下错误:无法推断通用参数“V”。
这是视图的使用方式ContentView
struct ContentView: View {
@Environment(\.managedObjectContext) var moc
@State private var lastNameFilter = "A"
var body: some View {
VStack {
// list of matching singers
FilteredList(filterKey: "lastName", filterValue: lastNameFilter, keyPath: \Singer.lastName, ascendingOrNot: true) { singer in
Text("\(singer.wrappedLastName)")
}
Button("Add Examples") {
let taylor = Singer(context: self.moc)
taylor.firstName = "Taylor"
taylor.lastName = "Swift"
let ed = Singer(context: self.moc)
ed.firstName = "Ed"
ed.lastName = "Sheeran"
let adele = Singer(context: self.moc)
adele.firstName = "Adele"
adele.lastName = "Adkins"
try? self.moc.save()
}
Button("Show A") {
self.lastNameFilter = "A"
}
Button("Show S") {
self.lastNameFilter = "S"
}
}
}
}
这是Singer
实体
extension Singer {
@nonobjc public class func fetchRequest() -> NSFetchRequest<Singer> {
return NSFetchRequest<Singer>(entityName: "Singer")
}
@NSManaged public var firstName: String?
@NSManaged public var lastName: String?
var wrappedFirstName: String {
firstName ?? "Unknown"
}
var wrappedLastName: String {
lastName ?? "Unknown"
}
}
非常感谢任何帮助。