首页 > 解决方案 > 如何使 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"
    }
}

非常感谢任何帮助。

标签: swiftgenericscore-datakeypaths

解决方案


推荐阅读