SwiftUI现在提供了一个新的、内置的修饰符,可以很容易地为任何视图自动生成一个占位符。例如,假设我们正在开发一个阅读文章的应用程序,它包含以下视图:
struct ArticleView: View {
var iconName: String
var title: String
var authorName: String
var description: String
var body: some View {
VStack(alignment: .leading) {
HStack {
Image(systemName: iconName)
.foregroundColor(.white)
.padding()
.background(Circle().fill(Color.secondary))
VStack(alignment: .leading) {
Text(title).font(.title)
Text("By " + authorName)
.font(.subheadline)
.foregroundColor(.gray)
}
}
Text(description).padding(.top)
}
.padding()
}
}
要为上面的视图生成一个占位符,我们现在要做的就是对它应用编辑修饰符,指定.placeholder作为编辑原因:
let placeholder = ArticleView(
iconName: "doc",
title: "Placeholder",
authorName: "Placeholder author",
description: String(repeating: "Placeholder ", count: 5)
)
.redacted(reason: .placeholder)
当这个修改器被应用时,所有在视图中显示的文本将被灰色的矩形所取代,所以我们在上面传递的实际字符串将只被用来确定这些矩形的大小。
值得注意的是,视图中包含的任何图像(比如ArticleView中显示的图标)仍然会像往常一样显示。 但是,我们可以使用新的redactionReasons环境值来调整这一行为——例如,通过实现一个包装器视图来读取该值,然后有条件地对给定视图应用一个modifier闭包,就像这样
struct RedactingView<Input: View, Output: View>: View {
var content: Input
var modifier: (Input) -> Output
@Environment(\.redactionReasons) private var reasons
var body: some View {
if reasons.isEmpty {
content
} else {
modifier(content)
}
}
}
有了上述两部分,我们现在可以在需要的时候轻松地应用我们自己的自定义编校逻辑,例如,当生成一个占位符时,可以在ArticleView中隐藏图像;
struct ArticleView: View {
...
var body: some View {
VStack(alignment: .leading) {
HStack {
Image(systemName: iconName)
.foregroundColor(.white)
.whenRedacted { $0.hidden() }
.padding()
.background(Circle().fill(Color.secondary))
...
}
Text(description).padding(.top)
}
.padding()
}
}
SwiftUI还提供了一种方法来取消编辑给定的子视图——这将使它像正常情况下一样渲染,即使它的父视图正在被编辑。下面是我们如何使用这个特性来始终显示我们的文章视图的标题,即使是在生成一个占位符的时候:
struct ArticleView: View {
...
var body: some View {
VStack(alignment: .leading) {
HStack {
Image(systemName: iconName)
...
VStack(alignment: .leading) {
Text(title).font(.title).unredacted()
...
}
}
Text(description).padding(.top)
}
.padding()
}
}
新的修订后的修饰符和它的兄弟api都是swift的内置功能中非常受欢迎的补充;当我们想要渲染一个正在加载内容的UI的“骨架”版本时,或者当创建一个小部件的预览实例时,它都是非常有用的。