我是一名 Java 开发人员,正在尝试学习 Swift/SwiftUI。我正在浏览 SwiftUI 的 Apple 教程 (https://developer.apple.com/tutorials/swiftui/creating-and-combining-views),其中包含以下代码片段:
import SwiftUI
@main
struct LandmarksApp: App {
var body: some Scene {
WindowGroup {
ContentView()
}
}
}
我试图理解这部分:
var body: some Scene {
WindowGroup {
ContentView()
}
}
据我所知,它创建了一个名为“场景”类型的主体的新变量。我知道你可以像这样实例化对象:
var x: String = "测试"
但我不熟悉语法。这会创建一个场景类型的新对象吗?
我已经浏览过this 但我在那里找不到这个语法。
最佳答案
对于 Swift 新手来说,这个语法确实很难破解。它涉及隐式 getter、构造函数、几种闭包快捷方式、隐式返回类型、泛型类型推断和不透明类型。让我们一步一步来。
计算属性的 Getter 语法
LandmarksApp
符合 App
协议(protocol)。这需要定义 body
符合 Scene
的类型的属性协议(protocol)。此外,我们在文档中得知 body
预计是只读计算属性。
computed property 的一般语法 的 getter 是:
var X : T {
get { ... }
...
}
但如果它是只读属性,则可以使用快捷方式:将 getter 代码直接放在类型后面的 block 中,并且不带 get
:
var CX : T { ... } // that's a computed property with its getter
此外,如果 getter 代码由单个表达式组成,则不需要返回:返回是隐式的。
使用闭包的 WindowGroup 构造函数
WindowsGroup
是我们要使用的类型。它符合 Scene
。它是基于类型参数 Content
的泛型类型符合 View
协议(protocol),我们有一个 ContentView
为了那个原因。所以这是第一次尝试:
struct LandmarksApp: App {
var body : WindowGroup<ContentView> { // read-only getter
WindowGroup<ContentView>(content: myhelper) // return a newly constructed object
}
}
WindowGroup<T>
的构造函数需要一个不带参数并返回 T
的函数作为参数。首先,使用一个普通函数。其定义如下:
func myhelper() -> ContentView {
return ContentView()
}
基于闭包和泛型的简化
我们可以用 closure 来简化 替换辅助函数:
var body : WindowGroup<ContentView> {
WindowGroup<ContentView>(content: { ()->ContentView in return ContentView() })
}
Swift 可以从上下文推断闭包中使用的类型,并且它还允许由单个表达式组成的闭包隐式返回。在没有参数的情况下,我们删除 in
。所有这些简化导致:
var body : WindowGroup<ContentView> {
WindowGroup<ContentView>(content: { ContentView() })
}
Swift 还能够从上下文中推断出泛型类型。所以这个表达式可以简化为:
var body : WindowGroup<ContentView> {
WindowGroup (content: { ContentView() })
}
最后但并非最不重要的,也是最棘手的部分:如果闭包是函数的最后一个参数,则 Swift 允许使用特殊语法。这称为尾随闭包。这导致:
var body : WindowGroup<ContentView> {
WindowGroup () { ContentView() }
}
此语法还允许去掉空括号:
var body : WindowGroup<ContentView> {
WindowGroup { ContentView() }
}
不透明类型
到目前为止,我们使用 body
具体的众所周知的类型。但是这个变量的类型不能推断出来吗?因此,很容易写成:
var body { // OUCH !!!
WindowGroup { ContentView() }
}
但是 Swift 要求计算属性具有显式类型。为了使其尽可能通用,但确保符合所需的协议(protocol),opaque type可以使用:
var body : some Scene {
WindowGroup { ContentView() }
}
有关不透明类型的更多信息,请参阅 this question .
总结
关于ios - SwiftUI - 此代码是否实例化一个新的场景对象?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65384567/