SwiftUI、tvOS、UIViewControllerRepresentable 和焦点问题

问题描述

我正在尝试在 tvOS SwiftUI 应用中实现搜索功能。我使用 UISearchController 作为最直接的解决方案来做到这一点。我将它包裹在符合 SearchViewUIViewControllerRepresentable 中。问题是,看起来焦点引擎拒绝将注意力集中在视图控制器 UI 的一部分 - UISearchBar 上。我可以在模拟器内从我的 Mac 输入搜索查询,以验证搜索是否有效,但当然,这不是真实的。

我尝试将 .focusable() 修饰符添加SearchView 中,但没有帮助。

还尝试在我的自定义子类 shouldUpdateFocuspreferredFocusEnvironments 中实现 didUpdateFocusUISearchControllerUISearchContainerViewController 回调,但根本没有调用它们。

我想我在这里遗漏了一些非常简单的东西。

这是 SearchView代码

struct SearchView: UIViewControllerRepresentable {
    
    @Binding var text: String

    typealias UIViewControllerType = UISearchContainerViewController

    typealias Context = UIViewControllerRepresentableContext<SearchView>
    
    func makeUIViewController(context: Context) -> UIViewControllerType {
        let controller = UISearchController(searchResultsController: context.coordinator)
        controller.searchResultsUpdater = context.coordinator
        return UISearchContainerViewController(searchController: controller)
    }

    func updateUIViewController(_ uiViewController: UIViewControllerType,context: Context) { }

    func makeCoordinator() -> SearchView.Coordinator {
        return Coordinator(text: $text)
    }

    class Coordinator: UIViewController,UISearchResultsUpdating {
        
        @Binding var text: String

        init(text: Binding<String>) {
            _text = text
            super.init(nibName: nil,bundle: nil)
        }

        func updateSearchResults(for searchController: UISearchController) {
            guard let searchText = searchController.searchBar.text else { return }
            text = searchText
        }
    
    }

}

还有主要的 ContentView(我去掉了一些不重要的代码):

struct ContentView: View {
    
    @State var model = ["aa","ab","bb","bc","cc","dd","ee"]
    @State var searchQuery: String = ""
    
    var body: some View {
        SearchView(text: $searchQuery)
        List {
            ForEach(model.filter({ $0.hasPrefix(searchQuery) })) { item in
                Text(item)
            }
        }
    }
}

tvOS

解决方法

最后,它可以通过 iOS 15 beta 1 中引入的 .searchable 修饰符完成,不再需要 UISearchController 包装器。

附言得到了 Apple 对此错误 (FB8974300) 的官方回应,还使用了 .searchable 修饰符,因此没有针对旧版本的修复。