siteline / swiftui-introspect

Introspect underlying UIKit/AppKit components from SwiftUI
MIT License
5.6k stars 348 forks source link

SearchField (.searchable) doesn't work with NavigationSplitView #421

Closed gojosh closed 3 months ago

gojosh commented 3 months ago

Description

I have tested SearchField with NavigationSplitView in the simplest possible test case. It works with NavigationStack, but no matter where you put the SearchField introspect, it won't work with NavigationSplitView.

Checklist

Expected behavior

This should print the statement: "Introspect working"

struct ContentView: View {

    @State var text = ""

    var body: some View {
        NavigationSplitView {
            VStack {
                Text("Hello, world!")
            }
            .searchable(text: $text)
        } detail: {
            Text("Detail View")
        }
        .introspect(.searchField, on: .iOS(.v15, .v16, .v17)) { searchField in
            print("Introspect working")
        }
    }
}

Actual behavior

Nothing is printed, no access to the searchField.

Steps to reproduce

No response

Version information

1.1.4

Destination operating system

iOS 17

Xcode version information

15.4

Swift Compiler version information

No response

gojosh commented 3 months ago

I solved the issue by creating an alternate SearchField with .from(UISplitViewController.self).

extension iOSViewVersion<SearchFieldSplitViewType, UISearchBar> {
    @available(*, unavailable, message: ".searchable isn't available on iOS 13")
    public static let v13 = Self.unavailable()
    @available(*, unavailable, message: ".searchable isn't available on iOS 14")
    public static let v14 = Self.unavailable()
    public static let v15 = Self(for: .v15, selector: selector)
    public static let v16 = Self(for: .v16, selector: selector)
    public static let v17 = Self(for: .v17, selector: selector)

    private static var selector: IntrospectionSelector<UISearchBar> {
        .from(UISplitViewController.self) {
            $0.viewIfLoaded?.allDescendants.lazy.compactMap { $0 as? UISearchBar }.first
        }
    }
}