Apple 为我们在 SwiftUI 中使用 UIKit 视图提供了两种方式
这些视图与布局系统交互的方式并没有很好的文档记录,并且正确实现它们可能会很麻烦。
RepresentableKit 旨在最大限度地减少使用 UIKit 视图的障碍,尤其是在预览中,手动修复布局问题是不合理的。我们提供了一个 UIViewRepresentable
的包装器,它抽象了 SwiftUI 内部的布局过程,并具有最有用(带有主观倾向)的默认布局处理。
一个最简单的使用示例是在预览中显示一个简单的、多行文本的 UILabel
。
import SwiftUI
import RepresentableKit
struct UILabel_Previews: PreviewProvider {
static var previews: some View {
UIViewAdaptor {
let view = UILabel()
view.numberOfLines = 0
view.text = "To love the journey is to accept no such end. I have found, through painful experience, that the most important step a person can take is always the next one."
return view
}
.padding()
}
}
请注意,如果我们天真地使用 UIViewRepresentable
而不进一步自定义布局来编写这段代码,它将渲染成单行文本。
有关更多示例,请参阅提供的 Examples
项目。
使用 Swift Package Manager 安装 RepresentableKit。
dependency
添加到您的 Package.swift
中。dependencies: [
.package(url: "https://github.com/yumemi-inc/RepresentableKit.git", .upToNextMajor(from: "0.1.0"))
]
让我们看看 UIViewRepresentable
如何为包含的 UIView 选择合适的尺寸。
首先我们需要了解的是通用的 SwiftUI 布局流程(来自 WWDC19: Building Custom Views with SwiftUI)。
第二个需要了解的知识点是,SwiftUI 视图对于每个维度都有 3 个尺寸值:最小 (min)、理想 (ideal)、最大 (max)。最小和最大值用于限制提议的尺寸,而理想尺寸在提议的尺寸为 nil 时使用(通过 .fixedSize() 视图修饰符实现)。
UIViewRepresentable
使用 Auto Layout intrinsic content size 和布局优先级来映射包含的 UIView 尺寸。
固有内容尺寸 (Intrinsic Content Size) | 抗压缩性 (Compression Resistance) | 吸附性 (Hugging) | 结果尺寸 |
---|---|---|---|
(-1) | - | - | 0 … 0 … ∞ |
x | < 750 | < 750 | 0 … x … ∞ |
x | < 750 | >= 750 | 0 … x … x |
x | >= 750 | < 750 | x … x … ∞ |
x | >= 750 | >= 750 | x … x … x |
min … ideal … max
-1
= UIView.noIntrinsicMetric
750
= UILayoutPriority.defaultHigh
UIViewRepresentable
还会监听 invalidateIntrinsicContentSize() 以更新其尺寸。
以 UILabel 为例,使用默认优先级和固有尺寸,它将映射到尺寸 x … x … ∞
,例如,它不会小于固有尺寸,但可以增长到任何尺寸;应用 fixedSize()
后,它将变为其固有内容尺寸。
然而,大多数自定义 UIView 没有固有尺寸,因此它们将映射到 0 … 0 … ∞
,例如,随着 SwiftUI 提议的任何值而增长和缩小,并在应用 fixedSize()
后消失(尺寸变为 0)。
RepresentableKit 通过两种方式抽象化了这些概念
您可以通过修改 UIViewAdaptor.init
属性来指定自定义的尺寸调整行为。
目前,RepresentableKit 不提供任何与 UIViewControllerRepresentable
的兼容性。