SwiftUI 中如何动态创建和过滤 FetchRequest

发布
更新
字数 341
阅读 2 分钟
阅读量 857

在 SwiftUI 中使用 Core Data,可以使用 property wrapper @FetchRequest 声明一个 FetchedResults 属性,自动从 Core Data 存储中获取一个数据集。参考文档:https://developer.apple.com/documentation/swiftui/fetchrequest Fetch request 需要使用环境变量 .managedObjectContext获取 Core Data 的 managed object context,通常在上一层视图注入:

ContentView()
    .environment(
        \.managedObjectContext,
        PersistenceController.shared.container.viewContext)

然后创建一个 fetch request

@FetchRequest(sortDescriptors: [SortDescriptor(\.time, order: .reverse)])
private var quakes: FetchedResults<Quake> // Quake 是 Core Data model

如何动态创建 FetchRequest

有时我们需要动态调整 fetch request 的 sortDescriptor 或者 nsPredicate 属性,实现排序、过滤、搜索等功能。

在初始化时创建 fetch request

// ...
@FetchRequest var fetchRequest: FetchedResults<Singer>

init(filter: String) {
    _fetchRequest = FetchRequest<Singer>(sortDescriptors: [], predicate: NSPredicate(format: "lastName BEGINSWITH %@", filter))
}

参考:https://www.hackingwithswift.com/books/ios-swiftui/dynamically-filtering-fetchrequest-with-swiftui

动态修改 fetch request

通过 FetchedResults 实例的 nsPredicatesortDescriptors 可以直接修改 fetch request 配置。

// ...
@State private var query = ""

// ...
.onChange(of: query) { value in
    quakes.nsPredicate = query.isEmpty
        ? nil
        : NSPredicate(format: "place CONTAINS %@", value)
}

与输入框绑定

如果我们需要根据一个输入框的输入内容过滤列表,例如自动完成的候选项,我们可以自定义绑定:

// @FetchRequest ...
// private var options ...
@State private input: String = ""
private var name: Binding<String> {
    get { input }
    set { newValue in
         input = bindingInput

         if newValue.isEmpty {
             options.nsPredicate = nil
             return
         }

         options.nsPredicate = NSPredicate(format: "name contains[cd] %@", newValue)
    }
}
//
TextFiled("Name", text: $name)

参考:https://developer.apple.com/documentation/swiftui/fetchrequest/configuration#Set-configuration-directly