Reputation: 4300
I am using a UIViewRepresentable to add a search bar to a SwiftUI project. The search bar is for searching the main List - I have setup the search logic and it works fine, however I have not been able to code the keyboard to disappear when the search is cancelled. The Cancel button does not respond. If I click the textfield clearButton the search is ended and the full list appears but the keyboard does not disappear. If I uncomment the resignFirstResponder line in textDidChange, the behavior is as expected, except that the keyboard disappears after every character.
Here's the search bar:
import Foundation
import SwiftUI
struct MySearchBar: UIViewRepresentable {
@Binding var sText: String
class Coordinator: NSObject, UISearchBarDelegate {
@Binding var sText: String
init(sText: Binding<String>) {
_sText = sText
}
func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
sText = searchText
//this works for EVERY character
//searchBar.resignFirstResponder()
}
}
func makeCoordinator() -> MySearchBar.Coordinator {
return Coordinator(sText: $sText)
}
func makeUIView(context: UIViewRepresentableContext<MySearchBar>) -> UISearchBar {
let searchBar = UISearchBar(frame: .zero)
searchBar.delegate = context.coordinator
searchBar.showsCancelButton = true
return searchBar
}
func updateUIView(_ uiView: UISearchBar, context: UIViewRepresentableContext<MySearchBar>) {
uiView.text = sText
}
func searchBarCancelButtonClicked(searchBar: UISearchBar) {
//this does not work
searchBar.text = ""
//none of these work
searchBar.resignFirstResponder()
searchBar.showsCancelButton = false
searchBar.endEditing(true)
}
}
And I load a MySearchBar in SwiftUI in the List.
var body: some View {
NavigationView {
List {
MySearchBar(sText: $searchTerm)
if !searchTerm.isEmpty {
ForEach(Patient.filterForSearchPatients(searchText: searchTerm)) { patient in
NavigationLink(destination: EditPatient(patient: patient, photoStore: self.photoStore, myTextViews: MyTextViews())) {
HStack(spacing: 30) {
//and the rest of the application
Xcode Version 11.2 beta 2 (11B44). SwiftUI. I have tested in the simulator and on a device. Any guidance would be appreciated.
Upvotes: 4
Views: 2682
Reputation: 111
The searchBarCancelButtonClicked
call will be passed to the UISearchBar
s delegate, which is set to Coordinator, so put func searchBarCancelButtonClicked
there instead.
Also, when you are clearing the text you shouldnt set searchBar.text = ""
, which is setting the instance of UISearchBar
s text property directly, but instead clear your Coordinators property text
. In that way your SwiftUI View will notice the change because of the @Binding
property wrapper, and know that it´s time to update.
Here is the complete code for `MySearchBar´:
import UIKit
import SwiftUI
struct MySearchBar : 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
searchBar.showsCancelButton = true
}
func searchBarCancelButtonClicked(_ searchBar: UISearchBar) {
text = ""
searchBar.showsCancelButton = false
searchBar.endEditing(true)
}
}
func makeCoordinator() -> SearchBar.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
}
}
Upvotes: 2
Reputation: 1041
The reason searchBarCancelButtonClicked
is not being called is because it is in MySearchBar
but you have set the Coordinator
as the search bars delegate. If you move the searchBarCancelButtonClicked
func to the Coordinator
, it will be called.
Here is what the coordinator should look like:
class Coordinator: NSObject, UISearchBarDelegate {
@Binding var sText: String
init(sText: Binding<String>) {
_sText = sText
}
func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
sText = searchText
}
func searchBarCancelButtonClicked(searchBar: UISearchBar) {
searchBar.text = ""
searchBar.resignFirstResponder()
searchBar.showsCancelButton = false
searchBar.endEditing(true)
}
}
Upvotes: 3