SwiftUI审查
注意
SwiftUIIntrospect
是一个基于原始审查
模块的所有新的模块,它在稳定性、可预测性和人体工程学方面进行了改进。这两个模块目前在同一仓库下共存,但计划最终废弃
审查
模块,以SwiftUI审查
作为1.0版的一部分。虽然
审查
支持Swift 5.5或更高版本,但SwiftUI审查
需要Swift 5.7或更高版本,这是因为它使用了更现代的语言特性,这部分上实现了上述改进。
SwiftUI审查允许您获取SwiftUI视图的底层的UIKit或AppKit元素。
例如,使用SwiftUI审查,您可以访问UITableView
来修改分隔符,或者访问UINavigationController
来自定义标签栏。
它如何工作
SwiftUI审查通过在所选视图上添加一个不可见的IntrospectionView
,在其下方添加一个不可见的“锚点”视图,然后在这两个视图之间的UIKit/AppKit视图层次结构中查找相关视图来实现。
例如,在审查ScrollView
时...
ScrollView {
Text("Item 1")
}
.introspect(.scrollView, on: .iOS(.v13, .v14, .v15, .v16, .v17)) { scrollView in
// do something with UIScrollView
}
...
- 它将向
TextField
添加IntrospectionView
作为叠加层 - 将
IntrospectionAnchorView
作为TextField
的背景。 - 遍历两个视图之间的所有子视图,直到找到
UIScrollView
实例(如果有的话)。
注意
尽管这种检查方法非常稳定且不会自身崩溃,但鉴于大型操作系统版本之间的底层 UIKit/AppKit 视图类型可能存在差异,未来操作系统版本需要显式启用检查(
.iOS(.vXYZ)
)。
默认情况下,.introspect
直接作用于其 接收器。这意味着在您尝试检查的视图内部调用 .introspect
不会产生任何效果。这与原始 Introspect
模块不同,其中一些视图从内部隐式允许检查。这是因为在大多数情况下,直接检查视图更为稳定和可预测,但有时这可能不适合库开发者。您可以使用 SwiftUIIntrospect
检查 祖先,但您必须明确通过重写检查 作用域 来启用此功能。
ScrollView {
Text("Item 1")
.introspect(.scrollView, on: .iOS(.v13, .v14, .v15, .v16, .v17), scope: .ancestor) { scrollView in
// do something with UIScrollView
}
}
生产中用法
SwiftUIIntrospect
预期为生产使用。它不使用任何私有 API。它仅使用公开可用的方法检查视图层次结构。该库在检查视图层次结构时采取了一种保守的方法:没有对元素布局做出硬性假设,没有对 UIKit/AppKit 类强制转换,如果在 UIKit/AppKit 视图中找不到视图,则简单地忽略 .introspect
修改器。
安装
Swift 包管理器
let package = Package(
dependencies: [
.package(url: "https://github.com/siteline/swiftui-introspect", from: "0.10.0"),
],
targets: [
.target(name: <#Target Name#>, dependencies: [
.product(name: "SwiftUIIntrospect", package: "swiftui-introspect"),
]),
]
)
CocoaPods
pod 'SwiftUIIntrospect'
自省
实现
按钮
颜色选择器
日期选择器
日期选择器
采用.compact
样式日期选择器
采用.field
样式日期选择器
采用.graphical
样式日期选择器
采用.stepperField
样式日期选择器
采用.wheel
样式表单
表单
采用.grouped
样式.fullScreenCover
列表
列表
采用.bordered
样式列表
采用.grouped
样式列表
采用.insetGrouped
样式列表
采用.inset
样式列表
采用.sidebar
样式列表项
地图
导航分割视图
导航堆叠
导航视图
采用.columns
样式导航视图
采用.stack
样式页面控件
选择器
采用.menu
样式选择器
采用.segmented
样式选择器
采用.wheel
样式.弹出视图
进度视图
采用.circular
样式进度视图
采用.linear
样式滚动视图
.可搜索的
安全字段
.表单
使用苹果ID登录按钮
滑块
步进器
表格
标签视图
标签视图
采用.page
样式文本编辑器
文本字段
文本字段
采用.vertical
轴样式切换
切换
采用button
样式切换
采用checkbox
样式切换
采用switch
样式视频播放器
视图
视图控制器
窗口
缺少一个元素?请创建一个问题。作为一个临时解决方案,您可以实现自己的可自省视图类型。
无法实现
SwiftUI | 受影响的框架 | 原因 |
---|---|---|
文本 | UIKit, AppKit | 不是UILabel / NSLabel |
图像 | UIKit, AppKit | 不是UIImageView / NSImageView |
按钮 | UIKit | 不是UIButton |
示例
列表
List {
Text("Item")
}
.introspect(.list, on: .iOS(.v13, .v14, .v15)) { tableView in
tableView.backgroundView = UIView()
tableView.backgroundColor = .cyan
}
.introspect(.list, on: .iOS(.v16, .v17)) { collectionView in
collectionView.backgroundView = UIView()
collectionView.subviews.dropFirst(1).first?.backgroundColor = .cyan
}
滚动视图
ScrollView {
Text("Item")
}
.introspect(.scrollView, on: .iOS(.v13, .v14, .v15, .v16, .v17)) { scrollView in
scrollView.backgroundColor = .red
}
导航视图
NavigationView {
Text("Item")
}
.navigationViewStyle(.stack)
.introspect(.navigationView(style: .stack), on: .iOS(.v13, .v14, .v15, .v16, .v17)) { navigationController in
navigationController.navigationBar.backgroundColor = .cyan
}
文本框
TextField("Text Field", text: <#Binding<String>#>)
.introspect(.textField, on: .iOS(.v13, .v14, .v15, .v16, .v17)) { textField in
textField.backgroundColor = .red
}
实现您自己的选择器
缺少一个元素?请创建一个问题。
如果SwiftUIIntrospect不支持您正在寻找的SwiftUI元素,您可以实现自己的选择器。例如,要监视一个TextField
@_spi(Advanced) import SwiftUIIntrospect
public struct TextFieldType: IntrospectableViewType {}
extension IntrospectableViewType where Self == TextFieldType {
public static var textField: Self { .init() }
}
#if canImport(UIKit)
extension iOSViewVersion<TextFieldType, UITextField> {
public static let v13 = Self(for: .v13)
public static let v14 = Self(for: .v14)
public static let v15 = Self(for: .v15)
public static let v16 = Self(for: .v16)
public static let v17 = Self(for: .v17)
}
extension tvOSViewVersion<TextFieldType, UITextField> {
public static let v13 = Self(for: .v13)
public static let v14 = Self(for: .v14)
public static let v15 = Self(for: .v15)
public static let v16 = Self(for: .v16)
public static let v17 = Self(for: .v17)
}
#elseif canImport(AppKit)
extension macOSViewVersion<TextFieldType, NSTextField> {
public static let v10_15 = Self(for: .v10_15)
public static let v11 = Self(for: .v11)
public static let v12 = Self(for: .v12)
public static let v13 = Self(for: .v13)
public static let v14 = Self(for: .v14)
}
#endif
发布
-
更新变更日志以包含新版本
-
将PR作为'Bump to X.Y.Z'提交并合并
-
标记新版本
$ git tag X.Y.Z $ git push origin --tags