如何使用SwiftUI显示搜索栏

如何使用SwiftUI显示搜索栏,swiftui,Swiftui,新的SwiftUI框架似乎没有提供内置的搜索栏组件。我应该使用UISearchController并以某种方式包装它,还是应该使用简单的textfield并根据textfield输入更新数据 编辑:当前的解决方法是使用TextField作为搜索栏。它工作得很好,但没有搜索图标 导入快捷界面 结构搜索:视图{ 让数组=[“John”、“Lena”、“Steve”、“Chris”、“Catalina”] @国家私有var searchText=“” var body:一些观点{ 导航视图{ 名单{

新的SwiftUI框架似乎没有提供内置的搜索栏组件。我应该使用UISearchController并以某种方式包装它,还是应该使用简单的textfield并根据textfield输入更新数据

编辑:当前的解决方法是使用
TextField
作为搜索栏。它工作得很好,但没有搜索图标

导入快捷界面
结构搜索:视图{
让数组=[“John”、“Lena”、“Steve”、“Chris”、“Catalina”]
@国家私有var searchText=“”
var body:一些观点{
导航视图{
名单{
TextField(“键入搜索”,text:$searchText)
.textFieldStyle(RoundedBorderTextFieldStyle())
ForEach(array.filter{$0.hasPrefix(searchText)| | searchText==“”},id:\.self){searchText in
文本(搜索文本)
}
}
.navigationBarTitle(文本(“搜索”))
}
}
}
结构搜索\u预览:PreviewProvider{
静态var预览:一些视图{
搜索()
}
}

更新为使用Xcode 11.1

许多UIKit组件目前没有SwiftUI等价物。为了使用它们,您可以创建包装器,如中所示

基本上,您可以创建一个符合UIViewRepresentable的SwiftUI类,并实现makeUIView和UpdateUI视图。

这个YouTube演示了如何实现它。归结起来是:

结构搜索栏:UIViewRepresentable{ @绑定变量文本:字符串 类协调器:NSObject,UISearchBarDelegate{ @绑定变量文本:字符串 init(文本:绑定){ _文本=文本 } func searchBar(searchBar:UISearchBar,textDidChange searchText:String){ 文本=搜索文本 } } func makeCoordinator()->SearchBar.Coordinator{ 退货协调员(文本:$text) } func makeUIView(上下文:UIViewRepresentableContext)->UISearchBar{ 让searchBar=UISearchBar(帧:.0) searchBar.delegate=context.coordinator searchBar.autocapitalizationType=.none 返回搜索栏 } func updateUIView(uiView:UISearchBar,context:UIViewRepresentableContext){ uiView.text=文本 } } 而不是

TextField($searchText)
              .textFieldStyle(.roundedBorder)
你用

SearchBar(text: $searchText)

这是一个纯swiftUI版本,基于对上面问题的回答以及我在和中发现的内容。它包括

  • 一个清晰的按钮
  • 取消按钮
  • 在列表中拖动时重新调整键盘,然后
  • 选择搜索文本字段时隐藏导航视图
在列表中拖动时重新调整键盘的大小可以使用以下UIApplication窗口上的方法实现。为了便于处理,我在UIApplication上创建了一个扩展,并为该扩展创建了视图修饰符,最后创建了视图扩展:

扩展应用程序{
函数定义(uForce:Bool){
自助窗口
.filter{$0.isKeyWindow}
.首先?
.endEditing(强制)
}
}
struct ResignKeyboardOnDragSignature:ViewModifier{
var-sirpose=DragGesture().onChanged{uu}in
UIApplication.shared.endEditing(true)
}
func正文(内容:内容)->某些视图{
内容.手势(手势)
}
}
扩展视图{
func辞职键盘OnDrag手势()->某些视图{
返回修饰符(ResignKeyboardOnDrag手势())
}
}
因此,调整键盘大小的最后一个修改器只是一个必须放在列表中的修改器,如下所示:

列表{
ForEach(…){
//...
}
}
.辞职KeyboardOnDrag手势()
搜索栏的完整swiftUI项目代码以及名称示例列表如下所示。您可以将其粘贴到新swiftUI项目的ContentView.swift中并使用它


导入快捷键
结构ContentView:View{
让数组=[“彼得”、“保罗”、“玛丽”、“安娜·莉娜”、“乔治”、“约翰”、“格雷格”、“托马斯”、“罗伯特”、“伯尼”、“迈克”、“本诺”、“雨果”、“迈尔斯”、“迈克尔”、“米克尔”、“蒂姆”、“汤姆”、“洛蒂”、“洛莉”、“芭芭拉”]
@国家私有var searchText=“”
@国家私有var showCancelButton:Bool=false
var body:一些观点{
导航视图{
VStack{
//搜索视图
HStack{
HStack{
图像(系统名称:“放大镜”)
TextField(“搜索”,text:$searchText,onEditingChanged:{isEditing in
self.showCancelButton=true
},电子委员会:{
打印(“onCommit”)
}).foregroundColor(.primary)
按钮(操作:{
self.searchText=“”
}) {
图像(系统名:“xmark.circle.fill”).opacity(searchText==”?0:1)
}
}
.填充(边集(顶部:8,前导:6,底部:8,尾随:6))
.foregroundColor(.secondary)
.background(颜色(.secondarySystemBackground))
.转弯半径(10.0)
如果显示取消按钮{
按钮(“取消”){
UIApplication.shared.endEditing(true)//这必须放在其他命令之前
self.searchText=“”
self.showCancelButton=false
}
.foregroundColor(颜色(.systemBlue))
}
}
.padding(.卧式)
.navigationBarHidden(showCancelButton)//.animation(.default)//动画无法正常工作
名单{
//筛选的名称列表
ForEach(array.filter{$0.hasPrefix(searchText)| | searchText==“”
import SwiftUI

struct SearchNavigation<Content: View>: UIViewControllerRepresentable {
    @Binding var text: String
    var search: () -> Void
    var cancel: () -> Void
    var content: () -> Content

    func makeUIViewController(context: Context) -> UINavigationController {
        let navigationController = UINavigationController(rootViewController: context.coordinator.rootViewController)
        navigationController.navigationBar.prefersLargeTitles = true
        
        context.coordinator.searchController.searchBar.delegate = context.coordinator
        
        return navigationController
    }
    
    func updateUIViewController(_ uiViewController: UINavigationController, context: Context) {
        context.coordinator.update(content: content())
    }
    
    func makeCoordinator() -> Coordinator {
        Coordinator(content: content(), searchText: $text, searchAction: search, cancelAction: cancel)
    }
    
    class Coordinator: NSObject, UISearchBarDelegate {
        @Binding var text: String
        let rootViewController: UIHostingController<Content>
        let searchController = UISearchController(searchResultsController: nil)
        var search: () -> Void
        var cancel: () -> Void
        
        init(content: Content, searchText: Binding<String>, searchAction: @escaping () -> Void, cancelAction: @escaping () -> Void) {
            rootViewController = UIHostingController(rootView: content)
            searchController.searchBar.autocapitalizationType = .none
            searchController.obscuresBackgroundDuringPresentation = false
            rootViewController.navigationItem.searchController = searchController
            
            _text = searchText
            search = searchAction
            cancel = cancelAction
        }
        
        func update(content: Content) {
            rootViewController.rootView = content
            rootViewController.view.setNeedsDisplay()
        }
        
        func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
            text = searchText
        }
        
        func searchBarSearchButtonClicked(_ searchBar: UISearchBar) {
            search()
        }
        
        func searchBarCancelButtonClicked(_ searchBar: UISearchBar) {
            cancel()
        }
    }
    
}
import SwiftUI

struct YourView: View {
    // Search string to use in the search bar
    @State var searchString = ""
    
    // Search action. Called when search key pressed on keyboard
    func search() {
    }
    
    // Cancel action. Called when cancel button of search bar pressed
    func cancel() {
    }
    
    // View body
    var body: some View {
        // Search Navigation. Can be used like a normal SwiftUI NavigationView.
        SearchNavigation(text: $searchString, search: search, cancel: cancel) {
            // Example SwiftUI View
            List(dataArray) { data in
                Text(data.text)
            }
            .navigationBarTitle("Usage Example")
        }
        .edgesIgnoringSafeArea(.top)
    }
}
struct DestinationPageView: View {
    @State private var text = ""
    var body: some View {
      NavigationView {
        PrimaryView()
        SecondaryView()
        Text("Select a primary and secondary item")
     }
     .searchable(text: $text)
  }
}
struct SearchableList: View {
    
    let groceries = ["Apple", "Banana", "Grapes"]
    @State private var searchText: String = ""
    
    var body: some View {
        NavigationView {
            List(searchResult, id: \.self) { grocerie in
                Button("\(grocerie)") { print("Tapped") }
            }
            .searchable(text: $searchText)
        }
    }
    
    var searchResult: [String] {
        guard !searchText.isEmpty else { return groceries }
        return groceries.filter { $0.contains(searchText) }
    }
}

struct SearchableList_Previews: PreviewProvider {
    static var previews: some View {
        SearchableList().previewLayout(.sizeThatFits)
    }
}