【问题标题】:SwiftUI searchbarSwiftUI 搜索栏
【发布时间】:2021-08-22 16:13:59
【问题描述】:

我正在尝试构建一个可以通过工作表显示不同 pdf 的应用程序。到目前为止一切顺利,但我希望用户能够过滤通过搜索栏触发工作表修饰符的按钮。这对我不起作用。我尝试了来自 web 和 Stack Overflow 的不同解决方案,但没有一个对我有用。我想我必须从触发布尔表的按钮中过滤文本。但是怎么做?使用 List 或 ForEach 我不能每次都使用不同的 var/Bool 按钮。

下面是我的 Searchbar 类,只有一个 List 并对其进行过滤。

class SearchBar: NSObject, ObservableObject {
    
    
    let searchController: UISearchController = UISearchController(searchResultsController: nil)
    
    @Binding var text: String
    let hide : Bool
    let placeholder : String
    let cancelButton : Bool
    let autocapitalization : UITextAutocapitalizationType
    
    init(text: Binding<String>, hide: Bool, placeholder: String, cancelButton: Bool, autocapitalization: UITextAutocapitalizationType) {
        
        self._text = text
        self.hide = hide
        self.placeholder = placeholder
        self.cancelButton = cancelButton
        self.autocapitalization = autocapitalization
        
        super.init()
        
        
        self.searchController.obscuresBackgroundDuringPresentation = false
        self.searchController.searchResultsUpdater = self
        
        self.searchController.hidesNavigationBarDuringPresentation = hide
        self.searchController.automaticallyShowsCancelButton = cancelButton
        self.searchController.searchBar.placeholder = placeholder
        self.searchController.searchBar.autocapitalizationType = autocapitalization
        
    }
}

extension SearchBar: UISearchResultsUpdating {
   
    func updateSearchResults(for searchController: UISearchController) {
        
        // Publish search bar text changes.
        if let searchBarText = searchController.searchBar.text {
            self.text = searchBarText
        }
    }
}

struct SearchBarModifier: ViewModifier {
    
    let searchBar: SearchBar
    
    func body(content: Content) -> some View {
        content
            .overlay(
                ViewControllerResolver { viewController in
                    viewController.navigationItem.searchController = self.searchBar.searchController
                }
                    .frame(width: 0, height: 0)
            )
    }
}

extension View {
    
    func add(_ searchBar: SearchBar) -> some View {
        return self.modifier(SearchBarModifier(searchBar: searchBar))
    }
    
}

【问题讨论】:

    标签: ios swiftui


    【解决方案1】:

    我的建议是将绑定替换为调用闭包并传递输入文本的操作。

    @Binding var text: String 行替换为

    var action : ((String) -> Void)?
    

    updateSearchResults 替换为

    func updateSearchResults(for searchController: UISearchController) {
        if let searchBarText = searchController.searchBar.text {
            DispatchQueue.main.async {  self.action?(searchBarText) }
        }
    }
    

    以及 ViewModifier 和视图扩展

    struct SearchBarModifier: ViewModifier {
        
        let searchBar: SearchBar
        let action : ((String) -> Void)?
        
        func body(content: Content) -> some View {
            content
                .overlay(
                    ViewControllerResolver { viewController in
                        searchBar.action = action
                        viewController.navigationItem.searchController = self.searchBar.searchController
                    }
                    .frame(width: 0, height: 0)
                )
        }
    }
    
    extension View {
       func add(_ searchBar: SearchBar, action : ((String) -> Void)?) -> some View {
           return self.modifier(SearchBarModifier(searchBar: searchBar, action: action))
       }
    }
    

    在视图中您可以添加搜索栏

    .add(self.searchBar, action: { query in
        // do something with query
    })
    

    只要用户按下某个键,就会调用闭包。

    如果您想在用户按下 Search/Go 键时调用一次闭包,您必须实现 searchBarSearchButtonClicked 并添加另一个操作。

    【讨论】:

    • 谢谢,我试试这个。但是 .add 修饰符位于带有按钮的 VStack 上,那么我应该如何处理查询?也许我真的有点迷路了
    • 一种有效的方法是在符合ObservableObject 的视图模型中过滤数据。在此类中创建一个 @Published 属性并将其设置在搜索栏闭包中。在另一个 @Published 属性中返回过滤后的数据,这会导致视图重新加载。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-10-22
    • 1970-01-01
    • 1970-01-01
    • 2021-12-07
    • 2021-05-21
    • 1970-01-01
    相关资源
    最近更新 更多