ios – Add a Inline Search Bar to Navigation Bar in SwiftUI


Context

We have an existing project which is build in UIKit, and now I want to have a new view created in SwiftUI with Search Bar stay on the navigation bar.

Which search bar is INLINE with the backBarButtonItem, so obviously modifier searchable cannot fulfill my requirement.

The simplify flow can be simplify like this
enter image description here

Issue

But when I try to do a proof of concept. The code will be at the last section of this question.

I found out that after pushing out the title of backBarButtonItem is shown at the first moment then disappear when the search bar added. Which is really bad in experience.

enter image description here

My Question

  1. Is there any way to fix?
  2. and why it is behavior like that?

Code

ViewController in UIKit

import UIKit

class ViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()

        view.backgroundColor = .white
        title = "Demo"

        navigationItem.rightBarButtonItem = UIBarButtonItem(barButtonSystemItem: .cancel, target: self, action: #selector(didSelectCancel(sender:)))
    }

    @objc func didSelectCancel(sender: UIBarButtonItem) {
        let hostingController = UIHostingController(rootView: MyView())
        self.navigationController?.pushViewController(hostingController, animated: true)
    }
}

MyView in SwiftUI

import SwiftUI

struct MyView: View {
    var body: some View {
        ScrollView {
            Text("Hello")
        }
        .toolbar {
            ToolbarItem(placement: .principal) {
                SearchBar(text: .constant("test"), placeholder: "test")
            }
        }
    }
}

SearchBar

Since SwiftUI doesn’t provide stand alone SearchBar, so I grab one from article Creating a search bar for SwiftUI and using it in my PoC

struct SearchBar: UIViewRepresentable {

    @Binding var text: String
    var placeholder: 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() -> SearchBar.Coordinator {
        return Coordinator(text: $text)
    }

    func makeUIView(context: UIViewRepresentableContext<SearchBar>) -> UISearchBar {
        let searchBar = UISearchBar(frame: .zero)
        searchBar.delegate = context.coordinator
        searchBar.placeholder = placeholder
        searchBar.searchBarStyle = .minimal
        searchBar.autocapitalizationType = .none
        return searchBar
    }

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

Latest articles

spot_imgspot_img

Related articles

Leave a reply

Please enter your comment!
Please enter your name here

spot_imgspot_img