SwiftUI中的内容是什么?
在文档中,我在不同的上下文中看到SwiftUI中的内容是什么?,swift,swiftui,Swift,Swiftui,在文档中,我在不同的上下文中看到内容: /// A modifier that can be applied to a view or other view modifier, /// producing a different version of the original value. @available(iOS 13.0, OSX 10.15, tvOS 13.0, watchOS 6.0, *) public protocol ViewModifier { /// The co
内容
:
/// A modifier that can be applied to a view or other view modifier,
/// producing a different version of the original value.
@available(iOS 13.0, OSX 10.15, tvOS 13.0, watchOS 6.0, *)
public protocol ViewModifier {
/// The content view type passed to `body()`.
typealias Content
}
这里呢
/// A view that arranges its children in a vertical line.
@available(iOS 13.0, OSX 10.15, tvOS 13.0, watchOS 6.0, *)
public struct VStack<Content> where Content : View {
///在垂直线上排列其子视图的视图。
@可用(iOS 13.0、OSX 10.15、tvOS 13.0、watchOS 6.0、*)
公共结构VStack,其中内容:查看{
我在文档中找不到对
内容
含义的正确解释。SwiftUI中是否有任何预定义的内容
用法?了解SwiftUI大量使用泛型类型非常重要。在SwiftUI(和Combine)发布之前,我从未见过任何Swift代码如此大量地使用泛型。SwiftUI中几乎所有的视图
-一致类型(和视图修改器
-一致类型)都是泛型类型
ViewModifier
因此,首先让我们讨论一下ViewModifier
ViewModifier
是一个协议。其他类型可以符合ViewModifier
,但没有变量或值可以只具有普通类型ViewModifier
为了使类型符合ViewModifier
,我们定义了一个body
方法,该方法接受内容(不管是什么),并返回body
(不管是什么):
ViewModifier
本质上就是这一种方法,它将内容
作为输入,并返回主体
作为输出
什么是Body
?ViewModifier
将其定义为带有约束的关联类型
:
associatedtype Body : View
这意味着我们可以在ViewModifier
中选择称为Body
的特定类型,并且我们可以为Body
选择任何类型,只要它符合视图
协议
任何内容
?文档告诉您它是类型别名
,这意味着我们可能无法选择它是什么。但是文档没有告诉您内容
是什么的别名,所以我们不知道正文
可以对它接收的内容
做什么
文档没有告诉您的原因是Xcode被编程为不显示SDK中的公共符号,如果该符号以下划线(\uuu
)开头但是,通过查看SwiftUI的.swiftinterface
文件,您可以看到ViewModifier
的真实定义,包括隐藏的符号。我解释了如何在中查找该文件
查阅该文件,我们找到了ViewModifier
的真正定义:
@available(iOS 13.0, OSX 10.15, tvOS 13.0, watchOS 6.0, *)
public protocol ViewModifier {
static func _makeView(modifier: SwiftUI._GraphValue<Self>, inputs: SwiftUI._ViewInputs, body: @escaping (SwiftUI._Graph, SwiftUI._ViewInputs) -> SwiftUI._ViewOutputs) -> SwiftUI._ViewOutputs
static func _makeViewList(modifier: SwiftUI._GraphValue<Self>, inputs: SwiftUI._ViewListInputs, body: @escaping (SwiftUI._Graph, SwiftUI._ViewListInputs) -> SwiftUI._ViewListOutputs) -> SwiftUI._ViewListOutputs
associatedtype Body : SwiftUI.View
func body(content: Self.Content) -> Self.Body
typealias Content = SwiftUI._ViewModifier_Content<Self>
}
请注意,我们不必命名body
返回的视图的类型。我们可以使用一些视图
,让Swift推断特定类型
我们可以这样使用它:
Text("Hello").modifier(MyModifier(color: .red))
VStack
现在我们来谈谈VStack
。VStack
类型是一个struct
,而不是一个协议。它是泛型的,这意味着它需要类型参数(就像函数需要函数参数一样).VStack
采用一个名为Content
的类型参数。这意味着VStack
定义了一个类型族,它允许内容的每种类型都有一个
由于VStack
的内容
参数被约束为符合视图
,这意味着对于每个符合视图
的类型,都有相应的VStack
类型。对于文本
(符合视图
),有VStack
。对于图像
,有VStack
。对于颜色
,有VStack
但是我们通常不会详细说明我们正在使用的VStack
的完整类型实例,而且我们通常不会让内容
类型像文本
或图像
那样是一个基本类型。使用VStack
的全部原因是在一列中排列多个视图。VStack
的使用告诉Swift去arra垂直调整其子视图,并且VStack
的Content
type参数指定子视图的类型
例如,当您编写以下内容时:
VStack {
Text("Hello")
Button(action: {}) {
Text("Tap Me!")
}
}
您实际上正在创建此类型的实例:
VStack<TupleView<(Text, Button<Text>)>>
VStack
这里的Content
type参数是typeTupleView
,它本身是一个泛型类型TupleView
,它自己的类型参数名为T
,而T
这里是(文本,按钮)
(一个2元组,也称为一对)因此类型的VStack
部分告诉SwiftUI垂直排列子视图,TupleView
部分告诉SwiftUI有两个子视图:一个Text
和一个按钮
您可以看到,即使是这个简短的示例,也是如何生成一个具有多个嵌套泛型参数级别的类型的。因此,我们肯定希望让编译器为我们找出这些类型。这就是为什么苹果在Swift中添加了some View
语法,以便让编译器找出确切的类型。这也可能有帮助:
private struct FormItem<Content:View>: View {
var label: String
let viewBuilder: () -> Content
var body: some View {
VStack(alignment: .leading, spacing: 4) {
Text(label).font(.headline)
viewBuilder()
}
}
}
因为viewBinder
是struct
的最后一个属性,所以您可以将内容放在FormItem
函数调用之后。我喜欢,当我发现这个问题时,这回答了我的隐式问题,但我想我可以扩展Kontiki的评论,适用于不熟悉Swift或泛型的程序员
这个问题问了几个问题,特别是:
SwiftUI中的内容是什么
令人惊讶的是,在SwiftUI中没有实际的内容
类或结构或类型(据我所知)!问题中的两个示例都提供了这方面的证据
我是什么意思?Content
是一个,有点像“保存类型的变量”(尽管我觉得这个解释令人困惑)
泛型真的很酷(这就是为什么Swift&XCode autocomplete知道你把字符串放在
VStack<TupleView<(Text, Button<Text>)>>
private struct FormItem<Content:View>: View {
var label: String
let viewBuilder: () -> Content
var body: some View {
VStack(alignment: .leading, spacing: 4) {
Text(label).font(.headline)
viewBuilder()
}
}
}
FormItem(label: "Your Name") {
TextField("name", text: $bindingToName)
}
VStack { // Function starts at `{`
Text("test")
Text("test 2")
} // Function ends at `}`