I am trying to to recreate what everyone know from UITableView with SwiftUI: A simple search field in the header of the tableview:
However, the List View in SwiftUI does not even seem to have a way to add a header or footer. You can set a header with a TextField to sections like this:
@State private var searchQuery: String = ""
var body: some View {
List {
Section(header:
Group{
TextField($searchQuery, placeholder: Text("Search"))
.background(Color.white)
}) {
ListCell()
ListCell()
ListCell()
}
}
}
However, I am not sure if this is the best way to do it because:
Has anyone found a good approach? I don't want to fall back on UITableView.
You can port UISearchBar
to SwiftUI.
(More about this can be found in the excellent WWDC 2019 talk - Integrating SwiftUI)
struct SearchBar: UIViewRepresentable {
@Binding var text: String
class Coordinator: NSObject, UISearchBarDelegate {
@Binding var text: String
init(text: Binding<String>) {
_text = text
}
func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
text = searchText
}
}
func makeCoordinator() -> Coordinator {
return Coordinator(text: $text)
}
func makeUIView(context: UIViewRepresentableContext<SearchBar>) -> UISearchBar {
let searchBar = UISearchBar(frame: .zero)
searchBar.delegate = context.coordinator
return searchBar
}
func updateUIView(_ uiView: UISearchBar,
context: UIViewRepresentableContext<SearchBar>) {
uiView.text = text
}
}
And use it like this:
struct ContentView: View {
@State private var searchQuery: String = ""
var body: some View {
List {
Section(header: SearchBar(text: self.$searchQuery)) {
ForEach(Array(1...100).filter {
self.searchQuery.isEmpty ?
true :
"\($0)".contains(self.searchQuery)
}, id: \.self) { item in
Text("\(item)")
}
}
}
}
}
It's the proper search bar, but it doesn't hide - I'm sure we'll be able to do it at some point via SwiftUI API.
Looks like this:
Updated for Xcode 11 beta 5