SwiftUI中的某些视图(例如VStack和HStack)支持将多个视图作为子视图,如下所示:
VStack {
Text("hello")
Text("world")
}
Run Code Online (Sandbox Code Playgroud)
从我收集,他们使用ViewBuilder使之成为可能的解释在这里。
我们如何使用@ViewBuilder创建自己的支持多个子视图的视图?例如,假设我要创建一个Layout接受任意子级的View,如下所示:
struct Layout : View {
let content: Some View
var body : some View {
VStack {
Text("This is a layout")
content()
}
}
}
Run Code Online (Sandbox Code Playgroud)
知道如何在SwiftUI中实现此模式吗?
这是一个不执行任何操作的示例视图,仅用于演示如何使用@ViewBuilder。
struct Passthrough<Content>: View where Content: View {
let content: () -> Content
init(@ViewBuilder content: @escaping () -> Content) {
self.content = content
}
var body: some View {
content()
}
}
Run Code Online (Sandbox Code Playgroud)
用法:
Passthrough {
Text("one")
Text("two")
Text("three")
}
Run Code Online (Sandbox Code Playgroud)
使用VStack我们需要@ViewBuilder用于我们的内容参数的声明。这是一个闭包,但它不应该是 @escaping 如果我们只需要来自它的数据,那么存储闭包就不好。我假设来自 Apple 声明。
我也认为这@inlinable很重要,因为:
@inlinable 属性将函数体作为模块接口的一部分导出,使其在被其他模块引用时可供优化器使用。 更多信息在这里
struct Layout <Content> : View where Content : View {
var content: Content
@inlinable public init(@ViewBuilder content: () -> Content) {
self.content = content()
}
var body : some View {
VStack {
Text("This is a layout")
self.content
}
}
}
Run Code Online (Sandbox Code Playgroud)
要使用它:
Layout {
Text("1")
VStack {
Text("1")
Text("2")
}
}
Run Code Online (Sandbox Code Playgroud)
UPD:
正如马特奥·帕西尼( Matteo Pacini)指出的那样,这是关于@escaping.
我们需要使用@escaping的DynamicViewContent意见。
@escaping用于接受集合(数组、范围等)的视图结构的 Apple 视图结构。因为ForEach实现DynamicViewContent- 一种从底层数据集合生成视图的视图。List在其初始值设定项中也在ForEach内容中
public init<Data, RowContent>(_ data: Data, selection: Binding<Selection>?, action: @escaping (Data.Element.IdentifiedValue) -> Void, rowContent: @escaping (Data.Element.IdentifiedValue) -> RowContent) where Content == ForEach<Data, Button<HStack<RowContent>>>, Data : RandomAccessCollection, RowContent : View, Data.Element : Identifiable
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
2141 次 |
| 最近记录: |