首页 > 解决方案 > SwiftUI UISearchController searchResultsController 导航堆栈问题

问题描述

UIViewControllerRepresentable有为 SwiftUI 制作的 UISearchController,如下所示:

struct SearchViewController<Content: View>: UIViewControllerRepresentable {
    var content: () -> Content
    let searchResultsView = SearchResultsView()

    init(@ViewBuilder content: @escaping () -> Content) {
        self.content = content
    }

    func makeUIViewController(context: Context) -> UINavigationController {

        let rootViewController = UIHostingController(rootView: content())
        let navigationController = UINavigationController(rootViewController: rootViewController)
        let searchResultsController = UIHostingController(rootView: searchResultsView)

        // Set nav properties
        navigationController.navigationBar.prefersLargeTitles = true
        navigationController.definesPresentationContext = true

        // Create search controller
        let searchController = UISearchController(searchResultsController: searchResultsController)
        searchController.searchBar.autocapitalizationType = .none
        searchController.delegate =  context.coordinator
        searchController.searchBar.delegate = context.coordinator // Monitor when the search button is tapped.

        // Create default view
        rootViewController.navigationItem.searchController = searchController
        rootViewController.title = "Search"

        return navigationController
    }

    func updateUIViewController(_ navigationController: UINavigationController, context: UIViewControllerRepresentableContext<SearchViewController>) {
        //
    }
}

这有效,并searchResultsController在用户搜索时显示。但是,searchResultsController似乎不知道它是导航上下文/堆栈,因此我无法从searchResultsController.

是否可以将其结构化以允许从 导航searchResultsController,或者这是当前 SwiftUI 的限制。

非常感谢任何建议!

标签: swiftswiftuiios13uisearchcontroller

解决方案


我最近还需要在我的应用程序中实现此功能(搜索栏,如导航栏)。看着你的片段真的启发了 m2!我先谢谢了!

在向你ula1990Lorenzo Boaro和V8tr学习之后,我实现了自己的。

我将其设置searchResultsControllernil(由于其中的导航链接不可点击,因此我将其设置为 nil)。

演示

代码:

struct SearchController<Result: View>: UIViewControllerRepresentable {
    @Binding var searchText: String
    private var content: (_ searchText:String)->Result
    
    private var searchBarPlaceholder: String
    

    init(_ searchBarPlaceholder: String = "", searchedText: Binding<String>,
         resultView: @escaping (_ searchText:String) -> Result) {
        self.content = resultView
        self._searchText = searchedText
        self.searchBarPlaceholder = searchBarPlaceholder
    }
    func makeUIViewController(context: Context) -> UINavigationController {
        let contentViewController = UIHostingController(rootView: SearchResultView(result: $searchText, content: content))
        let navigationController = UINavigationController(rootViewController: contentViewController)
        
        let searchController = UISearchController(searchResultsController: nil)
        searchController.searchResultsUpdater = context.coordinator
        searchController.obscuresBackgroundDuringPresentation = false // for results
        searchController.searchBar.placeholder = searchBarPlaceholder
        
        contentViewController.title = "\\(Title)" // for customization
        contentViewController.navigationItem.searchController = searchController
        contentViewController.navigationItem.hidesSearchBarWhenScrolling = true
        contentViewController.definesPresentationContext = true
        
        searchController.searchBar.delegate = context.coordinator
        
        return navigationController
    }
    
    func updateUIViewController(_ uiViewController: UINavigationController, context: UIViewControllerRepresentableContext<SearchController>) {
        // 
        
    }
}
extension SearchController {
    func makeCoordinator() -> SearchController<Result>.Coordinator {
        Coordinator(self)
    }
    class Coordinator: NSObject, UISearchResultsUpdating, UISearchBarDelegate {
        var parent: SearchController
        init(_ parent: SearchController){self.parent = parent}
        
        // MARK: - UISearchResultsUpdating
        func updateSearchResults(for searchController: UISearchController) {
            self.parent.searchText = searchController.searchBar.text!
        }
        
        // MARK: - UISearchBarDelegate
        func searchBarCancelButtonClicked(_ searchBar: UISearchBar) {
            self.parent.searchText = ""
        }

        func searchBarShouldBeginEditing(_ searchBar: UISearchBar) -> Bool {
            self.parent.searchText = ""
            return true
        }
    }
}

// "nofity" the result content about the searchText
struct SearchResultView<Content: View>: View { 
    @Binding var searchText: String
    private var content: (_ searchText:String)->Content
    init(result searchText: Binding<String>, @ViewBuilder content: @escaping (_ searchText:String) -> Content) {
        self._searchText = searchText
        self.content = content
    }
    var body: some View {
        content(searchText)
    }
}

如果这是您想要的,我不知道,但再次感谢!


推荐阅读