9.4 限定搜索操作的范围

原文链接: https://developer.apple.com/documentation/swiftui/scoping-a-search-operation

9.4 限定搜索操作的范围

把搜索空间划分为几个宽泛的类别。

概述

如果你要搜索的数据可以分为几个类别,就可以定义不同的作用域,帮助人们缩小搜索范围。定义作用域之后,SwiftUI 会呈现一个选择器,让人们从中选择一个。随后你把这个当前选中的作用域,作为搜索操作的输入之一。

定义可选的作用域

首先创建一个遵循 Hashable 协议的类型来表示可选的作用域。例如,你可以用枚举把商品搜索限定为只搜水果或只搜蔬菜:

1
2
3
4
enum ProductScope {
    case fruit
    case vegetable
}

然后创建属性来存储当前作用域,既可以作为视图中的状态变量,也可以作为模型中的已发布属性:

1
@Published var scope: ProductScope = .fruit

应用作用域

要使用作用域信息,请把当前作用域绑定到 searchScopes(_:scopes:) 修饰符。你还要提供一组与不同作用域对应的视图。与 searchSuggestions(_:) 修饰符一样,作用域修饰符作用于更靠近被修改视图的那个 searchable 修饰符,因此它需要跟在 searchable 修饰符之后:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
ProductList(departmentId: departmentId, productId: $productId)
    .searchable(text: $model.searchText, tokens: $model.tokens) { token in
        switch token {
        case .apple: Text("Apple")
        case .pear: Text("Pear")
        case .banana: Text("Banana")
        }
    }
    .searchScopes($model.scope) {
        Text("Fruit").tag(ProductScope.fruit)
        Text("Vegetable").tag(ProductScope.vegetable)
    }

SwiftUI 会用这个绑定和这些视图,向搜索框添加一个 Picker。默认情况下,在 macOS 上搜索处于激活状态时、或者在 iOS 上有人开始在搜索框中输入文本时,选择器会出现在搜索框下方:

macOS

一个带三个导航窗格的 macOS 窗口。左侧窗格列出 Produce、Frozen 和 Bakery 三项。中间窗格顶部有一个选择器,选项为 Fruit 和 Vegetable,当前选中 Vegetable。中间窗格列出商品,全是蔬菜。右侧窗格显示占位文本 Select a Product。工具栏在窗口右上角有一个搜索框,占位文本为 Search。

iOS

iOS 屏幕的一部分,显示一个占位文本为 Search 的搜索框。搜索框下方出现一个选择器,有两个选项 Fruit 和 Vegetable,当前选中 Vegetable。选择器下方显示一列蔬菜。

你也可以改用 searchScopes(:activation::) 修饰符,并提供 SearchScopeActivation 的某个取值(例如 onTextEntry 或 onSearchPresentation),来改变选择器出现的时机。

为确保选择器正常工作,请让作用域绑定的类型与每个视图标签的类型保持一致。在上面的例子中,scope 输入和每个视图的标签都是 ProductScope 类型。

如果你提供了作用域,请修改搜索逻辑,让它在查询的文本和令牌之外,也考虑 scope 属性的当前值。例如,你可以把作用域作为为 Core Data 获取请求定义的条件之一。关于执行搜索的更多信息,参见执行搜索操作。