如何在 iOS 的邮件应用程序上复制搜索选择?

How to replicate the search selection on iOS's Mail app?

我有一个 list,上面有一个 .searchable 搜索栏。它过滤包含文本和日期的结构。 我试图让用户 select 是 he/she 想要搜索包含特定文本的所有项目,还是搜索包含数据的所有项目。我认为当您点击顶部的搜索栏时 iOS Mail 执行此操作的方式是一种很好的方式(我对其他选项持开放态度...)。

看起来像这样:

因此,当您点击搜索字段时,选择器或两个按钮或选项卡 select 或会出现。我不太清楚是哪一个。无论如何,我尝试使用选择器,但是:

  1. 不知道放在哪里
  2. 我不知道如何在需要时隐藏它,然后再隐藏它。

这是基本代码:

let dateFormatter = DateFormatter()

struct LibItem: Codable, Hashable, Identifiable {
    let id: UUID
    var text: String
    var date = Date()
    var dateText: String {
        dateFormatter.dateFormat = "EEEE, MMM d yyyy, h:mm a"
        return dateFormatter.string(from: date)
    }
    var tags: [String] = []
}

final class DataModel: ObservableObject {
    @AppStorage("myapp") public var collectables: [LibItem] = []

    init() {
        self.collectables = self.collectables.sorted(by: {
            [=11=].date.compare(.date) == .orderedDescending
        })
    }

    func sortList() {
        self.collectables = self.collectables.sorted(by: {
            [=11=].date.compare(.date) == .orderedDescending
        })
    }    
}

struct ContentView: View {
    @EnvironmentObject private var data: DataModel
    @State var searchText: String = ""

    var body: some View {
        NavigationView {
            List(filteredItems) { collectable in
                VStack(alignment: .leading) {
                    Spacer() Text(collectable.dateText).font(.caption).fontWeight(.medium).foregroundColor(.secondary)
                    Spacer()
                    Text(collectable.text).font(.body).padding(.leading).padding(.bottom, 1)
                    Spacer()
                }
            }
            .listStyle(.plain)
            .searchable(
                text: $searchText,
                placement: .navigationBarDrawer(displayMode: .always),
                prompt: "Search..."
            )
        } 
    }

    var filteredItems: [LibItem] {
        data.collectables.filter {
        searchText.isEmpty ? true : [=11=].text.localizedCaseInsensitiveContains(searchText)
        }
    }
}

考虑到 isSearching:

,我试图添加类似的内容
@Environment(\.isSearching) var isSearching
var searchBy = [0, 1] // 0 = by text, 1 = by date
@State private var selectedSearch = 0

// Yes, I'd add the correct text to it, but I wanted to have it
// working first.
Picker("Search by", selection: $selectedColor) {
    ForEach(colors, id: \.self) {
          Text([=12=])
    }
}

我该怎么做?如何从 Mail 复制该搜索 UX?或者,有没有更好的方法让用户选择在用户点击搜索时显示的是搜索文本还是日期?

isSearching 适用于附加了 searchable 修饰符的子视图。所以,这样的事情会起作用:

struct ContentView: View {
    @EnvironmentObject private var data: DataModel
    @State var searchText: String = ""
    @State private var selectedItem = 0

    var body: some View {
        NavigationView {
            VStack {
                SearchableSubview(selectedItem: $selectedItem)
                List(filteredItems) { collectable in
                    VStack(alignment: .leading) {
                        Spacer()
                        Text(collectable.dateText).font(.caption).fontWeight(.medium).foregroundColor(.secondary)
                        Spacer()
                        Text(collectable.text).font(.body).padding(.leading).padding(.bottom, 1)
                        Spacer()
                    }
                }
                .listStyle(.plain)
                
            }.searchable(
                text: $searchText,
                placement: .navigationBarDrawer(displayMode: .always),
                prompt: "Search..."
            )
        }
    }

    var filteredItems: [LibItem] {
        data.collectables.filter {
        searchText.isEmpty ? true : [=10=].text.localizedCaseInsensitiveContains(searchText)
        }
    }
}

struct SearchableSubview : View {
    @Environment(\.isSearching) private var isSearching
    @Binding var selectedItem : Int

    var body: some View {
        if isSearching {
            Picker("Search by", selection: $selectedItem) {
                Text("Choice 1").tag(0)
                Text("Choice 2").tag(1)
            }.pickerStyle(.segmented)
        }
    }
}