SwiftUIIntrospect is an all-new module based off the original Introspect module that improves on stability, predictability, and ergonomics.
Both modules currently live together under this repo, but the plan is to ultimately obsolete Introspect in favor of SwiftUIIntrospect as part of a 1.0 release.
Introspect allows you to get the underlying UIKit or AppKit element of a SwiftUI view.
For instance, with Introspect you can access UITableView to modify separators, or UINavigationController to customize the tab bar.
How it works
Introspect works by adding a custom IntrospectionView to the view hierarchy, then looking into the UIKit hierarchy to find the relevant view.
For instance, when introspecting a TextField, it will:
Add IntrospectionView as an overlay of TextField
Get the view host of the introspection view (which is alongside the view host of the UITextField)
Get the previous sibling containing UITextField
Please note that this introspection method might break in future SwiftUI releases. Future implementations might not use the same hierarchy, or might not use UIKit elements that are being looked for. Though the library is unlikely to crash, the .introspect() method will not be called in those cases.
Usage in production
Introspect is meant to be used in production. It does not use any private API. It only inspects the view hierarchy using publicly available methods. The library takes a defensive approach to inspecting the view hierarchy: there is no hard assumption that elements are laid out a certain way, there is no force-cast to UIKit classes, and the introspect() methods are simply ignored if UIKit views cannot be found.
In case Introspect doesn’t support the SwiftUI element that you’re looking for, you can implement your own selector. For example, to look for a UITextField:
Introspect for SwiftUI
For instance, with Introspect you can access
UITableView
to modify separators, orUINavigationController
to customize the tab bar.How it works
Introspect works by adding a custom
IntrospectionView
to the view hierarchy, then looking into the UIKit hierarchy to find the relevant view.For instance, when introspecting a
TextField
, it will:IntrospectionView
as an overlay ofTextField
UITextField
)UITextField
Please note that this introspection method might break in future SwiftUI releases. Future implementations might not use the same hierarchy, or might not use UIKit elements that are being looked for. Though the library is unlikely to crash, the
.introspect()
method will not be called in those cases.Usage in production
Introspect
is meant to be used in production. It does not use any private API. It only inspects the view hierarchy using publicly available methods. The library takes a defensive approach to inspecting the view hierarchy: there is no hard assumption that elements are laid out a certain way, there is no force-cast to UIKit classes, and theintrospect()
methods are simply ignored if UIKit views cannot be found.Install
SwiftPM
Cocoapods
Introspection
Implemented
.introspectNavigationController()
.introspectSplitViewController()
.introspectSplitView()
.introspectViewController()
.introspectScrollView()
.introspectTableView()
introspectTableViewCell()
.introspectCollectionView()
.introspectCollectionViewCell()
.introspectTabBarController()
(iOS).introspectTabView()
(macOS).introspectTextField()
.introspectSwitch()
(iOS).introspectButton()
(macOS).introspectSlider()
.introspectStepper()
.introspectDatePicker()
.introspectSegmentedControl()
.introspectButton()
.introspectColorWell()
.introspectTextView()
Missing an element? Please create an issue. As a temporary solution, you can implement your own selector.
Cannot implement
Examples
List
ScrollView
NavigationView
TextField
Implement your own selector
Missing an element? Please create an issue.
In case Introspect doesn’t support the SwiftUI element that you’re looking for, you can implement your own selector. For example, to look for a
UITextField
:You can use any of the following methods to inspect the hierarchy:
Introspect.findChild(ofType:in:)
Introspect.findChildUsingFrame(ofType:in:from:)
Introspect.previousSibling(containing:from:)
Introspect.nextSibling(containing:from:)
Introspect.findAncestor(ofType:from:)
Introspect.findHostingView(from:)
Introspect.findViewHost(from:)
Releasing
Update changelog with new version
PR as ‘Bump to X.Y.Z’ and merge it
Tag new version: