SwiftUI-Inspect

GithubCI_Status Quintschaf_Badge

Inspect 是一种从 SwiftUI 中更安全、更 Swift 地访问 UIKit 和 AppKit 组件的新方法。它深受 SwiftUI-Introspect 的启发,但未使用任何旧代码。

覆盖范围

SwiftUI UIKit AppKit 注意
TextField (文本框) UITextField NSTextField
TextEditor (文本编辑器) UITextEditor NSTextView
ScrollView (滚动视图) UIScrollView NSScrollView
List/Form (列表/表单) ListInspectionNativeView* NSTableView
any View (任何视图) ListCellInspectionNativeView* 尚未实现 可以在代表 ListForm Cell (单元格) 的任何视图上调用此方法。该函数名为 inspectListOrFormCell
Button (按钮) 没有原生控件 NSButton
Toggle (开关) UISwitch NSButton
Slider (滑块) UISlider NSSlider
Stepper (步进器) UIStepper NSStepper
DatePicker (日期选择器) UIDatePicker NSDatePicker
Picker (选择器) UISegmentedControl NSSegmentedControl 目前仅支持 PickerStyle.segmentedControl 样式,因此该方法名为 inspectSegmentedControl
ColorPicker (颜色选择器) UIColorWell NSColorWell
NavigationView / NavigationStack (导航视图/导航栈) UINavigationController / UISplitViewController / UINavigationBar 没有相关的原生控件 默认函数 inspect 返回一个 UINavigationControllerUISplitViewController 可通过 inspectSplitViewController 访问,UINavigationBar 可通过 inspectNavigationBar 访问。
TabView (标签栏视图) UITabBarController / UITabBar 没有相关的原生控件 默认函数 inspect 返回一个 UITabBarControllerUITabBar 可通过 inspectTabBar 访问。

*在 iOS 上,根据环境和操作系统版本,ListForm 可以是 UITableViewUICollectionView,因此它们的子视图可以是 UITableViewCellUICollectionViewCellListInspectionNativeViewListCellInspectionNativeView 是枚举,它们包含找到的视图作为关联值(例如 ListInspectionNativeView.tableView(UITableView))。在大多数情况下,您应该同时支持这两种情况。

为什么它比 Introspect 更安全、更 Swift?

Inspect 和 Introspect 之间最大的区别是

  1. Inspect 不假设严格的视图层次结构(例如,要搜索的视图是 InspectionView 的父视图的子视图),而是遍历视图层次结构的各个层级,直到找到正确的视图。它通过将 InspectionView 的框架与任何潜在结果候选者的框架进行匹配来实现。
  2. 通过搜索具有正确框架的视图,可以避免我们在 Introspect 中遇到的一些问题,例如,当将多个相同类型的视图添加到 VStack 或 HStack 并检查其中一个时,Inspect 将检索正确的视图,而 Introspect 通常检索第一个视图。
  3. Inspect 的公共 API 大量采用了 Swift 强大的类型系统。您只能对与要搜索的 UIKit 或 AppKit 类型相对应的 SwiftUI 类型调用 inspect。例如,在 iOS 上,您在 SwiftUI TextField 上调用 inspect() 并获得一个 UITextField。您不能调用 inspect() 在任何其他 SwiftUI 类型上检索 UITextField,甚至在修改过的 TextField 上也不行。这不适用于 UITableViewCellUICollectionViewCell,它们没有对应的 SwiftUI 类型。

它是如何工作的?

Inspect 的工作原理是将 InspectionView 作为背景视图添加到视图层次结构中。然后,它查找一个具有与 InspectionView 相同的全局框架并且是您要查找的类型的视图。在某些情况下,当查找的框架与 InspectionView 的框架不同时,情况会稍微复杂一些,但您可以通过查看代码找到所有这些。

请注意,此内省方法可能会在未来的 SwiftUI 版本中失效。未来的实现可能不会使用正在查找的 UIKit 元素。虽然该库不太可能崩溃,但在这些情况下不会调用 .inspect() 方法。

在生产环境中使用

Inspect 可以在生产环境中使用,并遵循一些操作规则

示例

TextField (文本框)

TextField("Placeholder", text: $textValue)
.inspect { field in
    field.layer.backgroundColor = UIColor.red.cgColor
}

安装

SwiftPM

https://github.com/quintschaf/SwiftUI-Inspect.git

待办事项

特别感谢

特别感谢 Siteline、Loïs Di Qual 以及 SwiftUI-Introspect 的所有其他贡献者,感谢他们的诸多启发。