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
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.
My Question
- Is there any way to fix?
- 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
}
}