Skip to content

Commit 46a563f

Browse files
rzulkoskiRyan Zulkoskidavdroman
authored
Fix view controller introspection (#165)
Co-authored-by: Ryan Zulkoski <[email protected]> Co-authored-by: David Roman <[email protected]>
1 parent e4d9b8d commit 46a563f

File tree

2 files changed

+29
-22
lines changed

2 files changed

+29
-22
lines changed

Introspect/UIKitIntrospectionView.swift

+14-14
Original file line numberDiff line numberDiff line change
@@ -45,29 +45,29 @@ public struct UIKitIntrospectionView<TargetViewType: UIView>: UIViewRepresentabl
4545
self.customize = customize
4646
}
4747

48+
/// When `makeUIView` and `updateUIView` are called, the Introspection view is not yet in the UIKit hierarchy.
49+
/// At this point, `introspectionView.superview.superview` is nil and we can't access the target UIKit view.
50+
/// To workaround this, we wait until the runloop is done inserting the introspection view in the hierarchy, then run the selector.
51+
/// Finding the target view fails silently if the selector yields no result. This happens when the introspection view gets
52+
/// removed from the hierarchy.
4853
public func makeUIView(context: UIViewRepresentableContext<UIKitIntrospectionView>) -> IntrospectionUIView {
4954
let view = IntrospectionUIView()
5055
view.accessibilityLabel = "IntrospectionUIView<\(TargetViewType.self)>"
51-
return view
52-
}
53-
54-
/// When `updateUiView` is called after creating the Introspection view, it is not yet in the UIKit hierarchy.
55-
/// At this point, `introspectionView.superview.superview` is nil and we can't access the target UIKit view.
56-
/// To workaround this, we wait until the runloop is done inserting the introspection view in the hierarchy, then run the selector.
57-
/// Finding the target view fails silently if the selector yield no result. This happens when `updateUIView`
58-
/// gets called when the introspection view gets removed from the hierarchy.
59-
public func updateUIView(
60-
_ uiView: IntrospectionUIView,
61-
context: UIViewRepresentableContext<UIKitIntrospectionView>
62-
) {
63-
uiView.moveToWindowHandler = {
56+
view.moveToWindowHandler = { [weak view] in
57+
guard let view = view else { return }
6458
DispatchQueue.main.async {
65-
guard let targetView = self.selector(uiView) else {
59+
guard let targetView = self.selector(view) else {
6660
return
6761
}
6862
self.customize(targetView)
6963
}
7064
}
65+
return view
7166
}
67+
68+
public func updateUIView(
69+
_ uiView: IntrospectionUIView,
70+
context: UIViewRepresentableContext<UIKitIntrospectionView>
71+
) {}
7272
}
7373
#endif

Introspect/UIKitIntrospectionViewController.swift

+15-8
Original file line numberDiff line numberDiff line change
@@ -31,25 +31,32 @@ public struct UIKitIntrospectionViewController<TargetViewControllerType: UIViewC
3131
self.customize = customize
3232
}
3333

34+
/// When `makeUIViewController` and `updateUIViewController` are called, the Introspection view is not yet in
35+
/// the UIKit hierarchy. At this point, `introspectionViewController.parent` is nil and we can't access the target
36+
/// UIKit view controller. To workaround this, we wait until the runloop is done inserting the introspection view controller's
37+
/// view in the hierarchy, then run the selector. Finding the target view controller fails silently if the selector yields no result.
38+
/// This happens when the introspection view controller's view gets removed from the hierarchy.
3439
public func makeUIViewController(
3540
context: UIViewControllerRepresentableContext<UIKitIntrospectionViewController>
3641
) -> IntrospectionUIViewController {
3742
let viewController = IntrospectionUIViewController()
3843
viewController.accessibilityLabel = "IntrospectionUIViewController<\(TargetViewControllerType.self)>"
3944
viewController.view.accessibilityLabel = "IntrospectionUIView<\(TargetViewControllerType.self)>"
45+
(viewController.view as? IntrospectionUIView)?.moveToWindowHandler = { [weak viewController] in
46+
guard let viewController = viewController else { return }
47+
DispatchQueue.main.async {
48+
guard let targetView = self.selector(viewController) else {
49+
return
50+
}
51+
self.customize(targetView)
52+
}
53+
}
4054
return viewController
4155
}
4256

4357
public func updateUIViewController(
4458
_ uiViewController: IntrospectionUIViewController,
4559
context: UIViewControllerRepresentableContext<UIKitIntrospectionViewController>
46-
) {
47-
DispatchQueue.main.async {
48-
guard let targetView = self.selector(uiViewController) else {
49-
return
50-
}
51-
self.customize(targetView)
52-
}
53-
}
60+
) {}
5461
}
5562
#endif

0 commit comments

Comments
 (0)