SwiftUI 从另一个视图中捕获 Picker 值

Posted

技术标签:

【中文标题】SwiftUI 从另一个视图中捕获 Picker 值【英文标题】:SwiftUI Catch the Picker value from another view 【发布时间】:2021-02-08 08:46:22 【问题描述】:

我需要在选择器中添加搜索栏和 nil 值。我想创建一个自定义选择器并在任何地方使用它以避免代码重复。我能够使用 this 和 this 代码创建选择器,但我找不到如何捕获我在另一个视图中选择的值。

这段代码帮助我在选择器中进行搜索。

    struct SearchBar: UIViewRepresentable 

    @Binding var text: String
    var placeholder: String

    func makeUIView(context: UIViewRepresentableContext<SearchBar>) -> UISearchBar 
        let searchBar = UISearchBar(frame: .zero)
        searchBar.delegate = context.coordinator

        searchBar.placeholder = placeholder
        searchBar.autocapitalizationType = .none
        searchBar.searchBarStyle = .minimal
        return searchBar
    

    func updateUIView(_ uiView: UISearchBar, context: UIViewRepresentableContext<SearchBar>) 
        uiView.text = text
    

    func makeCoordinator() -> SearchBar.Coordinator 
        return Coordinator(text: $text)
    

    class Coordinator: NSObject, UISearchBarDelegate 

        @Binding var text: String

        init(text: Binding<String>) 
            _text = text
        

        func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) 
            text = searchText
        
    

这是我创建的自定义选择器。

struct CustomPicker<Item>: View where Item: Hashable 
    let items: [Item]
    let title: String
    let text: KeyPath<Item, String>
    let needOptional: Bool
    let needSearchBar: Bool
    
    @State var item: Item? = nil
    @State var searchText: String = ""
    
    var filteredItems: [Item] 
        items.filter 
            searchText.isEmpty ? true : $0[keyPath: text].lowercased().localizedStandardContains(searchText.lowercased())
        
    
    
    var body: some View 
        Picker(selection: $item, label: Text(title)) 
            if needSearchBar 
                SearchBar(text: $searchText, placeholder: "Search")
                    .padding(.horizontal, -12)
            
            
            if needOptional 
                Text("[none]").tag(nil as Item?)
                    .foregroundColor(.red)
            
            
            ForEach(filteredItems, id: \.self)  item in
                Text(item[keyPath: text])
                    .tag(item as Item?)
            
        
        .onAppear
            searchText = ""
        
    

用法

国家模式示例

struct Country: Codable, Identifiable, Hashable 
    let id = UUID()
    let name: String

    enum CodingKeys: String, CodingKey 
        case id, name
    

在内容视图中

Form 
CustomPicker(items: countryArray, title: "Country", text: \Country.name, needOptional: true, needSearchBar: true)

如何在 ContentView 中捕获选定的项目(可选)?

【问题讨论】:

【参考方案1】:

使用@Binding绑定你的物品。

struct CustomPicker<Item>: View where Item: Hashable 
    let items: [Item]
    let title: String
    let text: KeyPath<Item, String>
    let needOptional: Bool
    let needSearchBar: Bool
    
    @Binding var item: Item? // <--Here
    @State var searchText: String = ""
    
    
    //-----Other code---------//

并在内容视图中使用@State 获取所选值。

struct ContentView: View 
    
    @State private var selectedItem: Country? //<-- Here
    
    private let countryArray: [Country] = [.init(name: "A"), .init(name: "B")]
    
    var body: some View 
        Form 
            CustomPicker(items: countryArray, title: "Country", text: \Country.name, needOptional: true, needSearchBar: true, item: $selectedItem) // <-- Here
            if let selectedItem = selectedItem 
                Text(selectedItem.name)
            
        
    

【讨论】:

谢谢,我试过@Binding var item: Item? = 每次都为零。

以上是关于SwiftUI 从另一个视图中捕获 Picker 值的主要内容,如果未能解决你的问题,请参考以下文章

SwiftUI Picker 在同一视图中更改第二个状态变量

为 SwiftUI 寻找一个简单的自定义视图:picker

如何让 SwiftUI Picker 在子视图中工作? (变灰)

视图中的 SwiftUI Picker 会在点击时自行禁用

没有标签的 SwiftUI Picker 视图

SwiftUI Picker 视图中不显示值