RepresentableKit

Apple 为我们在 SwiftUI 中使用 UIKit 视图提供了两种方式

  1. UIViewRepresentable
  2. UIViewControllerRepresentable

这些视图与布局系统交互的方式并没有很好的文档记录,并且正确实现它们可能会很麻烦。

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。

dependencies: [
    .package(url: "https://github.com/yumemi-inc/RepresentableKit.git", .upToNextMajor(from: "0.1.0"))
]

UIViewRepresentable

让我们看看 UIViewRepresentable 如何为包含的 UIView 选择合适的尺寸。

首先我们需要了解的是通用的 SwiftUI 布局流程(来自 WWDC19: Building Custom Views with SwiftUI)。

  1. 父视图为子视图提议一个尺寸
  2. 子视图选择自己的尺寸
  3. 父视图将子视图放置在父视图的坐标空间中

第二个需要了解的知识点是,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

UIViewRepresentable 还会监听 invalidateIntrinsicContentSize() 以更新其尺寸。

以 UILabel 为例,使用默认优先级和固有尺寸,它将映射到尺寸 x … x … ∞,例如,它不会小于固有尺寸,但可以增长到任何尺寸;应用 fixedSize() 后,它将变为其固有内容尺寸。

然而,大多数自定义 UIView 没有固有尺寸,因此它们将映射到 0 … 0 … ∞,例如,随着 SwiftUI 提议的任何值而增长和缩小,并在应用 fixedSize() 后消失(尺寸变为 0)。

RepresentableKit 通过两种方式抽象化了这些概念

  1. UIViewFlexibility 通过布局优先级来控制最小/最大尺寸。
  2. UIViewIdealSizeCalculator 用于控制理想尺寸。

您可以通过修改 UIViewAdaptor.init 属性来指定自定义的尺寸调整行为。

UIViewControllerRepresentable

目前,RepresentableKit 不提供任何与 UIViewControllerRepresentable 的兼容性。