在 SwiftUI 的 #Preview 中预览任意 UIKit 视图的轻量工具。用一个简洁的 PreviewViewController,即可在不运行模拟器的情况下快速查看 UIView 的外观与布局效果。
- 目标:让传统 UIKit 视图在 SwiftUI 预览面板中即时可视化,提升 UI 开发与调试效率。
- 特性:
- 支持三种尺寸决策策略:显式
frame.size、sizeThatFits(_:)、Auto Layout 的systemLayoutSizeFitting。 - 支持使用
CGFloat.infinity作为「跟容器同宽/同高/填满容器」的声明方式。 - 未能确定有效尺寸时会抛出错误,提示开发者补充尺寸信息。
- 无需 Storyboard/Nib,纯代码即可预览。
- 支持三种尺寸决策策略:显式
-
Xcode 添加依赖:
- 打开你的项目或 Package;
- File → Add Packages…;
- 输入本仓库地址(例如
https://github.com/sondra/UIKitPreview.git); - 选择合适的版本规则后添加。
-
直接在
Package.swift中添加(示例):
// swift-tools-version: 5.9
import PackageDescription
let package = Package(
name: "YourApp",
platforms: [.iOS(.v17)],
dependencies: [
.package(url: "https://github.com/sondra/UIKitPreview.git", from: "0.1.0")
],
targets: [
.target(
name: "YourApp",
dependencies: [
.product(name: "UIKitPreview", package: "UIKitPreview")
]
)
]
)PreviewViewController 提供两种初始化方式:
- 直接传入已构造的
UIView:PreviewViewController(yourView) - 通过构建闭包:
PreviewViewController { /* 构建并返回 UIView */ }
基础示例:
import UIKit
import UIKitPreview
#Preview {
PreviewViewController {
let view = UIView(frame: CGRect(x: 0, y: 0, width: 120, height: 80))
view.backgroundColor = .systemPink
return view
}
}PreviewViewController 会按以下优先级决定被预览视图的尺寸:
- 显式尺寸:若
view.frame.size为有效非零值,优先使用。- 当
width或height为CGFloat.infinity时,表示该维度与容器一致; - 当二者均为
CGFloat.infinity时,填满容器。
- 当
sizeThatFits(_:):调用view.sizeThatFits(containerSize)取得期望尺寸。- Auto Layout:使用
view.systemLayoutSizeFitting(UIView.layoutFittingCompressedSize)。
若以上都无法得到有效尺寸(非零且大于 0),将抛出错误提醒你提供尺寸策略。
以下示例与库内默认示例一致,可直接复制到你的预览文件中试用:
// 示例1: 外部设置固定 size
#Preview {
PreviewViewController {
let view = UIView(frame: CGRect(x: 0, y: 0, width: 100, height: 100))
view.backgroundColor = .red
return view
}
}
// 示例2: 设置为跟容器一样大(使用 infinity)
#Preview {
PreviewViewController {
let view = UIView(frame: CGRect(x: 0, y: 0, width: CGFloat.infinity, height: CGFloat.infinity))
view.backgroundColor = .blue
return view
}
}
// 示例3: 依赖 Auto Layout (systemLayoutSizeFitting)
#Preview {
PreviewViewController {
let label = UILabel()
label.text = "Hello World"
label.sizeToFit()
return label
}
}
// 示例4: 自定义 sizeThatFits
#Preview {
PreviewViewController {
let customView = CustomView()
return customView
}
}
internal class CustomView: UIView {
override func sizeThatFits(_ size: CGSize) -> CGSize {
return CGSize(width: 200, height: 150)
}
}- 若使用
sizeThatFits(_:),请返回有效非零尺寸。 - 若依赖 Auto Layout,请确保子视图及约束能够在压缩尺寸下计算出期望大小(必要时调整 Hugging/Compression Resistance)。
- 预览逻辑运行在主线程环境,请避免在预览构建中进行耗时操作。
- 需要 Xcode 15+(支持
#Preview宏),建议 iOS 13+。 - Swift 5.9 或更高版本。
本项目使用 MIT 许可证,详情见仓库内 LICENSE 文件。