SwiftUI - 此代码是否实例化一个新的场景对象?

are*_*y11 2 syntax ios swift swiftui

我是一名 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()
        }
    }
}

Run Code Online (Sandbox Code Playgroud)

我试图理解这部分:

    var body: some Scene {
        WindowGroup {
            ContentView()
        }
    }
Run Code Online (Sandbox Code Playgroud)

据我所知,它创建了一个名为“场景”类型的主体的新变量。我知道你可以像这样实例化对象: var x: String = "test" 但我不熟悉语法。这会创建一个场景类型的新对象吗?

我已经经历过这个 ,但我在那里找不到这个语法。

Chr*_*phe 5

对于 Swift 新手来说,这个语法确实很难破解。它涉及隐式 getter、构造函数、几种闭包快捷方式、隐式返回类型、泛型类型推断和不透明类型。让我们一步一步来。

计算属性的 Getter 语法

LandmarksApp符合App协议。这就需要定义body符合协议的类型的属性Scene。此外,文档中告诉我们,body预计将是只读计算属性。

计算属性的 getter的一般语法是:

var X : T {
    get { ... }
    ...
}
Run Code Online (Sandbox Code Playgroud)

但如果它是只读属性,则可以使用快捷方式:将 getter 代码直接放在类型后面的块中,并且不带get

var CX : T { ... }   // that's a computed property with its getter
Run Code Online (Sandbox Code Playgroud)

此外,如果 getter 代码由单个表达式组成,则不需要返回:返回是隐式的。

使用闭包的 WindowGroup 构造函数

WindowsGroup是我们要使用的类型。它符合Scene. 它是基于Content符合View协议的类型参数的泛型类型,我们有一个ContentView。所以这是第一次尝试:

struct LandmarksApp: App {
    var body : WindowGroup<ContentView> {      // read-only getter 
        WindowGroup<ContentView>(content: myhelper)  // return a newly constructed object 
    }
}
Run Code Online (Sandbox Code Playgroud)

for 的构造WindowGroup<T>函数需要一个不带参数并返回 a 的函数作为参数T。首先,使用一个普通函数。它的定义如下:

func myhelper() -> ContentView {
    return ContentView()
}
Run Code Online (Sandbox Code Playgroud)

基于闭包和泛型的简化

我们可以用闭包来替换辅助函数来简化:

var body : WindowGroup<ContentView> {
    WindowGroup<ContentView>(content: { ()->ContentView in return ContentView() })
}
Run Code Online (Sandbox Code Playgroud)

Swift 可以从上下文中推断出闭包中使用的类型,并且它还允许由单个表达式组成的闭包隐式返回。在没有参数的情况下,我们删除in. 所有这些简化导致:

var body : WindowGroup<ContentView> {
    WindowGroup<ContentView>(content: { ContentView() })
}
Run Code Online (Sandbox Code Playgroud)

Swift 还能够从上下文中推断出泛型类型。所以这个表达式可以简化为:

var body : WindowGroup<ContentView> {
    WindowGroup (content: { ContentView() })
}
Run Code Online (Sandbox Code Playgroud)

最后但并非最不重要的,也是最棘手的部分:如果闭包是函数的最后一个参数,则 Swift 允许使用特殊语法。这称为尾随闭包。这导致:

var body : WindowGroup<ContentView> {
    WindowGroup () { ContentView() } 
}
Run Code Online (Sandbox Code Playgroud)

此语法还允许去掉空括号:

var body : WindowGroup<ContentView> {
    WindowGroup { ContentView() } 
}
Run Code Online (Sandbox Code Playgroud)

不透明类型

到目前为止,我们使用的是一种body众所周知的具体类型。但是这个变量的类型不能推断出来吗?因此,很容易写成:

var body {  // OUCH !!!
    WindowGroup { ContentView() } 
}
Run Code Online (Sandbox Code Playgroud)

但 Swift 要求计算属性具有显式类型。为了使其尽可能通用但确保符合所需的协议,可以使用不透明类型:

var body : some Scene {
    WindowGroup { ContentView() }
}
Run Code Online (Sandbox Code Playgroud)

有关此问题的不透明类型的更多信息。

包起来

在此输入图像描述

  • 看来 Swift 语言有太多语法糖难以理解。 (5认同)