You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
> [`SwiftUIIntrospect`]([email protected]#L19) is an all-new module based off the original [`Introspect`](Package.swift#L13) module that improves on stability, predictability, and ergonomics.
4
-
>
5
-
> 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.
6
-
>
7
-
> Read the [`SwiftUIIntrospect` documentation](docs/SwiftUIIntrospect.md) to learn more.
1
+
SwiftUI Introspect
2
+
=================
8
3
9
-
Introspect for SwiftUI
10
-
======================
4
+
[](https://github.com/siteline/SwiftUI-Introspect/actions/workflows/ci.yml)
> [`SwiftUIIntrospect`](../[email protected]#L19) is an all-new module based off the original [`Introspect`](../Package.swift#L13) module that improves on stability, predictability, and ergonomics.
10
+
>
11
+
> 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.
12
+
>
13
+
> While `Introspect` supports Swift 5.5 or higher, `SwiftUIIntrospect` requires Swift 5.7 or higher due to the use of more recent language features which partially enable the aforementioned improvements over the original.
13
14
14
-
> Introspect allows you to get the underlying UIKit or AppKit element of a SwiftUI view.
15
+
SwiftUIIntrospect allows you to get the underlying UIKit or AppKit element of a SwiftUI view.
15
16
16
-
For instance, with Introspect you can access `UITableView` to modify separators, or `UINavigationController` to customize the tab bar.
17
+
For instance, with SwiftUIIntrospect you can access `UITableView` to modify separators, or `UINavigationController` to customize the tab bar.
17
18
18
19
How it works
19
20
------------
20
21
21
-
Introspect works by adding a custom `IntrospectionView` to the view hierarchy, then looking into the UIKit hierarchy to find the relevant view.
22
+
SwiftUIIntrospect works by adding an invisible `IntrospectionView` on top of the selected view, and an invisible "anchor" view underneath it, then looking through the UIKit/AppKit view hierarchy between the two to find the relevant view.
23
+
24
+
For instance, when introspecting a `ScrollView`...
25
+
26
+
```swift
27
+
ScrollView {
28
+
Text("Item 1")
29
+
}
30
+
.introspect(.scrollView, on: .iOS(.v13, .v14, .v15, .v16, .v17)) { scrollView in
31
+
// do something with UIScrollView
32
+
}
33
+
```
34
+
35
+
... it will:
22
36
23
-

37
+
- Add `IntrospectionView` as an overlay of `TextField`
38
+
- Add `IntrospectionAnchorView` as the background of `TextField`.
39
+
- Traverse through all the subviews between both views until a `UIScrollView` instance (if any) is found.
24
40
25
-
For instance, when introspecting a `TextField`, it will:
41
+
> **Warning**
42
+
>
43
+
> Although this introspection method itself is very solid and unlikely to break in itself, future OS releases require explicit opt-in for introspection (`.iOS(.vXYZ)`), given differences between major OS versions which might not use the same UIKit/AppKit elements that are being looked for in previous OS versions.
26
44
27
-
- Add `IntrospectionView` as an overlay of `TextField`
28
-
- Get the view host of the introspection view (which is alongside the view host of the `UITextField`)
29
-
- Get the previous sibling containing `UITextField`
45
+
By default, `.introspect` works directly on its _receiver_. This means calling `.introspect` from inside the view you're trying to introspect won't have any effect. This is different to the original `Introspect` module in which some views would implicitly allow introspection from within. This is because most of the time it's more stable and predictable to introspect views directly, but there are times when it's not possible or simply too inflexible for library developers. You **can** introspect an _ancestor_ with `SwiftUIIntrospect`, but you must opt into this explicitly by overriding the introspection `scope`:
30
46
31
-
**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.
47
+
```swift
48
+
ScrollView {
49
+
Text("Item 1")
50
+
.introspect(.scrollView, on: .iOS(.v13, .v14, .v15, .v16, .v17), scope: .ancestor) { scrollView in
51
+
// do something with UIScrollView
52
+
}
53
+
}
54
+
```
32
55
33
56
### Usage in production
34
57
35
-
`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.
36
-
58
+
`SwiftUIIntrospect` 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/AppKit classes, and the `introspect()` methods are simply ignored if UIKit/AppKit views cannot be found.
**Missing an element?** Please [create an issue](https://github.com/timbersoftware/SwiftUI-Introspect/issues). As a temporary solution, you can [implement your own selector](#implement-your-own-selector).
-[`DatePicker` with `.compact` style](https://swiftpackageindex.com/siteline/swiftui-introspect/master/documentation/swiftuiintrospect/datepickerwithcompactstyletype)
93
+
-[`DatePicker` with `.field` style](https://swiftpackageindex.com/siteline/swiftui-introspect/master/documentation/swiftuiintrospect/datepickerwithfieldstyletype)
94
+
-[`DatePicker` with `.graphical` style](https://swiftpackageindex.com/siteline/swiftui-introspect/master/documentation/swiftuiintrospect/datepickerwithgraphicalstyletype)
95
+
-[`DatePicker` with `.stepperField` style](https://swiftpackageindex.com/siteline/swiftui-introspect/master/documentation/swiftuiintrospect/datepickerwithstepperfieldstyletype)
96
+
-[`DatePicker` with `.wheel` style](https://swiftpackageindex.com/siteline/swiftui-introspect/master/documentation/swiftuiintrospect/datepickerwithwheelstyletype)
-[`Form` with `.grouped` style](https://swiftpackageindex.com/siteline/swiftui-introspect/master/documentation/swiftuiintrospect/formwithgroupedstyletype)
-[`List` with `.bordered` style](https://swiftpackageindex.com/siteline/swiftui-introspect/master/documentation/swiftuiintrospect/listwithborderedstyletype)
102
+
-[`List` with `.grouped` style](https://swiftpackageindex.com/siteline/swiftui-introspect/master/documentation/swiftuiintrospect/listwithgroupedstyletype)
103
+
-[`List` with `.insetGrouped` style](https://swiftpackageindex.com/siteline/swiftui-introspect/master/documentation/swiftuiintrospect/listwithinsetgroupedstyletype)
104
+
-[`List` with `.inset` style](https://swiftpackageindex.com/siteline/swiftui-introspect/master/documentation/swiftuiintrospect/listwithinsetstyletype)
105
+
-[`List` with `.sidebar` style](https://swiftpackageindex.com/siteline/swiftui-introspect/master/documentation/swiftuiintrospect/listwithsidebarstyletype)
-[`NavigationView` with `.columns` style](https://swiftpackageindex.com/siteline/swiftui-introspect/master/documentation/swiftuiintrospect/NavigationViewWithColumnsStyleType)
110
+
-[`NavigationView` with `.stack` style](https://swiftpackageindex.com/siteline/swiftui-introspect/master/documentation/swiftuiintrospect/NavigationViewWithStackStyleType)
111
+
-[`Picker` with `.menu` style](https://swiftpackageindex.com/siteline/swiftui-introspect/master/documentation/swiftuiintrospect/pickerwithmenustyletype)
112
+
-[`Picker` with `.segmented` style](https://swiftpackageindex.com/siteline/swiftui-introspect/master/documentation/swiftuiintrospect/pickerwithsegmentedstyletype)
113
+
-[`Picker` with `.wheel` style](https://swiftpackageindex.com/siteline/swiftui-introspect/master/documentation/swiftuiintrospect/pickerwithwheelstyletype)
-[`ProgressView` with `.circular` style](https://swiftpackageindex.com/siteline/swiftui-introspect/master/documentation/swiftuiintrospect/progressviewwithcircularstyletype)
116
+
-[`ProgressView` with `.linear` style](https://swiftpackageindex.com/siteline/swiftui-introspect/master/documentation/swiftuiintrospect/progressviewwithlinearstyletype)
-[`TabView` with `.page` style](https://swiftpackageindex.com/siteline/swiftui-introspect/master/documentation/swiftuiintrospect/TabViewWithPageStyleType)
-[`TextField` with `.vertical` axis](https://swiftpackageindex.com/siteline/swiftui-introspect/master/documentation/swiftuiintrospect/TextFieldWithVerticalAxisType)
-[`Toggle` with `button` style](https://swiftpackageindex.com/siteline/swiftui-introspect/master/documentation/swiftuiintrospect/togglewithbuttonstyletype)
131
+
-[`Toggle` with `checkbox` style](https://swiftpackageindex.com/siteline/swiftui-introspect/master/documentation/swiftuiintrospect/togglewithcheckboxstyletype)
132
+
-[`Toggle` with `switch` style](https://swiftpackageindex.com/siteline/swiftui-introspect/master/documentation/swiftuiintrospect/togglewithswitchstyletype)
**Missing an element?** Please [create an issue](https://github.com/timbersoftware/SwiftUI-Introspect/issues). As a temporary solution, you can [implement your own introspectable view type](#implement-your-own-view-type).
82
138
83
139
### Cannot implement
84
140
@@ -95,26 +151,25 @@ Examples
95
151
96
152
```swift
97
153
List {
98
-
Text("Item 1")
99
-
Text("Item 2")
154
+
Text("Item")
100
155
}
101
-
.introspectTableView { tableView in
102
-
tableView.separatorStyle= .none
156
+
.introspect(.list, on: .iOS(.v13, .v14, .v15)) { tableView in
157
+
tableView.backgroundView=UIView()
158
+
tableView.backgroundColor= .cyan
103
159
}
104
-
.introspectTableViewCell { cell in
105
-
let backgroundView =UIView()
106
-
backgroundView.backgroundColor= .clear
107
-
cell.selectedBackgroundView= backgroundView
160
+
.introspect(.list, on: .iOS(.v16, .v17)) { collectionView in
.introspect(.textField, on: .iOS(.v13, .v14, .v15, .v16, .v17)) { textField in
194
+
textField.backgroundColor= .red
139
195
}
140
196
```
141
197
@@ -144,33 +200,40 @@ Implement your own selector
144
200
145
201
**Missing an element?** Please [create an issue](https://github.com/timbersoftware/SwiftUI-Introspect/issues).
146
202
147
-
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`:
203
+
In case SwiftUIIntrospect doesn't support the SwiftUI element that you're looking for, you can implement your own selector. For example, to introspect a `TextField`:
You can use any of the following [methods](https://github.com/timbersoftware/SwiftUI-Introspect/blob/master/Introspect/Introspect.swift#L3-L71) to inspect the hierarchy:
0 commit comments