Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

SwiftUI Wrapped SearchBar Can't Dismiss Keyboard

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.

like image 944
JohnSF Avatar asked Sep 07 '25 10:09

JohnSF


1 Answers

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)
    }
}
like image 117
Vlad Avatar answered Sep 10 '25 13:09

Vlad