Closed bdashore3 closed 1 year ago
Hi @bdashore3. I think in general what we're facing now that Introspect is more resilient to SwiftUI's weird view lifecycle thanks to #165, #192 and #196 is that we should expect multiple calls to the customize callback to be performed. So this needs to be accounted for in situations where you don't just mutate some properties in your introspected view, but when you add new views to the hierarchy as they'll pile up indefinitely as you're seeing here.
I'll take a look at your example and come back to you shortly.
@bdashore3 here's the solution:
struct MainView: View {
enum ViewTab {
case home
case search
}
@State private var selectedTab: ViewTab = .home
var body: some View {
TabView(selection: $selectedTab) {
InternalView()
.tabItem {
Label("Home", systemImage: "house")
}
.tag(ViewTab.home)
InternalView()
.tabItem {
Label("Search", systemImage: "magnifyingglass")
}
.tag(ViewTab.search)
}
}
}
struct InternalView: View {
@State private var searchText = ""
var body: some View {
NavigationView {
List {
ForEach(1..<100) { num in
Text(String(num))
}
}
.searchable(text: $searchText, placement: .navigationBarDrawer(displayMode: .always))
.navigationBarTitle("Search", displayMode: .large)
.customScopeBar()
}
}
}
extension View {
func customScopeBar() -> some View {
self.modifier(CustomScopeBarModifier())
}
}
struct CustomScopeBarModifier: ViewModifier {
@State private var hostingController: UIViewController?
func body(content: Content) -> some View {
content
.introspectSearchController { searchController in
// if we've already set up the hosting controller before, don't do this at all
guard hostingController == nil else { return }
searchController.hidesNavigationBarDuringPresentation = true
searchController.searchBar.showsScopeBar = true
searchController.searchBar.scopeButtonTitles = [""]
(searchController.searchBar.value(forKey: "_scopeBar") as? UIView)?.isHidden = true
let hostingController = UIHostingController(rootView: FilterView())
hostingController.view.translatesAutoresizingMaskIntoConstraints = false
hostingController.view.backgroundColor = .clear
guard let containerView = searchController.searchBar.value(forKey: "_scopeBarContainerView") as? UIView else {
return
}
searchController.navigationItem.hidesSearchBarWhenScrolling = false
containerView.addSubview(hostingController.view)
NSLayoutConstraint.activate([
hostingController.view.widthAnchor.constraint(equalTo: containerView.widthAnchor),
hostingController.view.topAnchor.constraint(equalTo: containerView.topAnchor),
hostingController.view.heightAnchor.constraint(equalTo: containerView.heightAnchor)
])
// saves the hosting controller's reference for the check at the top
self.hostingController = hostingController
}
.introspectNavigationController { navigationController in
navigationController.navigationBar.prefersLargeTitles = true
navigationController.navigationBar.sizeToFit()
}
}
}
struct FilterView: View {
@State private var textName = "first"
@State private var secondTextName = "First"
var body: some View {
Picker("", selection: $textName) {
Text("First").tag("first")
Text("Second").tag("second")
}
.pickerStyle(.segmented)
}
}
Let me know if you have any questions.
There's still a little UI jolt when switching tabs for the first time due to the customization happening on the next thread hop after the search view controller is actually created, but after that it looks totally fine. I have some ideas on how to get rid of the thread hop but I need to spend some time on it. At least now I have a reliable reproducible scenario to work on :)
I thought that was the case. Thanks for the tip! Closing this issue.
Hi there, I recently updated to Introspect v0.2.2 and had an issue when using
addSubview
that I've never seen before. Basically, when I switch back and forth between views that useaddSubview
in an introspect call (example: TabView tabs), multiple subviews are overlaid on top of each other causing application lag and weird UI bugs.I included my sample code below to showcase this problem. I basically add a custom scope bar with a segmented picker to the underlying UISearchController of searchable. To reproduce this bug:
I reverted back to v0.2.1 and this issue did not occur. Am I supposed to change something in my code for v0.2.2 compatability or is this a mistake in the library?