Search code examples
iosswiftswiftuiuisearchbarxcode11

UISearchBar "X" button not triggering any event on some views


I've implemented a simple UISearchBar, however, the "X" button just works when I call the search bar directly. Why is that?

Here is my code:

UISearchBar

struct SearchBarView: View, 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() -> SearchBarView.Coordinator {
        return Coordinator(text: $text)
    }

    func makeUIView(context: UIViewRepresentableContext<SearchBarView>) -> UISearchBar {
        let searchBar = UISearchBar(frame: .zero)
        searchBar.delegate = context.coordinator
        searchBar.autocapitalizationType = .none
        searchBar.enablesReturnKeyAutomatically = true
        searchBar.showsSearchResultsButton = true
        searchBar.setBackgroundImage(UIImage(), for: .any, barMetrics: .default)
        searchBar.searchTextField.backgroundColor = UIColor.init(red: 239/255, green: 239/255, blue: 239/255, alpha: 1)
        searchBar.isTranslucent = true
        searchBar.placeholder = "Pesquisar"
        return searchBar
    }

    func updateUIView(_ uiView: UISearchBar, context: UIViewRepresentableContext<SearchBarView>) {
        uiView.text = text
    }
}

My TopBarView in another file

struct TopBarView: View {
    @EnvironmentObject var environmentController : EnvironmentController

    var body: some View {
        HStack() {
            Button(action: {
                self.environmentController.environment.showMenu.toggle()
            }) {
                Image(systemName: "line.horizontal.3")
                    .background(
                        RoundedRectangle(cornerRadius: 8.0)
                            .foregroundColor(Color.init(red: 239/255, green: 239/255, blue: 239/255))
                            .frame(width: 36, height: 36, alignment: .center))
                    .foregroundColor(.black)
                    .imageScale(.large)
                    .font(.subheadline)
                    .frame(width: 40, height: 40, alignment: .center)
            }
            SearchBarView(text: self.$environmentController.environment.searchText)
        }
        .padding(.top, 30)
        .padding(.all)
    }
}

My MainView, also in another file

struct NextDeparturesView: View {
    @ObservedObject var userSettingsController = UserSettingsController()
    @EnvironmentObject var environmentController : EnvironmentController
    @State private var showMap = false

    var body: some View {
        VStack() {
            //If showUserActionSheet is false or showMap is true, display the menu button, the search bar and the map
            if(!self.userSettingsController.showUserCityActionSheet || showMap) {
                MapView()
                    .overlay(
                        TopBarView(),
                        alignment: .top)
                    .edgesIgnoringSafeArea(.top)
                    .onTapGesture {
                        if(self.environmentController.environment.showMenu) {
                            self.environmentController.environment.showMenu.toggle()
                        }
                }
            }
        }

So, if in my MainView I call the SearchBarView directly, the "x" button works. However, if I use the TopBarView, as in the code, the "x" button stops working. It may also be worth mentioning that writing in the search bar always works, it is just the "x" button that stops working.

I'm new to swift, what am I missing?

Thanks

EDIT

I still can't figure this out, but I guess it stops working when inside the overlay. In my MainView, if I move the TopBarView() call outside the overlay, it works.

EDIT2

So, if I add allowHitTesting(false) to my MainView overlay, the UISearchBar starts working, however, the menu button stops... If you have only one action in your overlay, this might be the solution for you.


Solution

  • Ok, so if anyone finds themselves in the same position as me and can't find a solution, the only way I got it to work was to abandon the overlay and develop a more complex view using ZStack.

    In the question edits you can see what I tried before, maybe it will help you.

    I'll accept this as the answer, however, if someone eventually comes up with a better solution, I will change it.