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

标签 ios swift swiftui syntax

我是一名 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 .

总结

enter image description here

关于ios - SwiftUI - 此代码是否实例化一个新的场景对象?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65384567/

相关文章:

ios - swift 和 Xcode : How to have a default list of countries?

ios - 如何始终转换到 iOS 中选项卡的初始 View ?

ios - 无法从 Firebase 数据库检索数据

ios - 将两个同名的 .swift 文件添加到项目中

ios - UIAlertController .actionSheet 项目之间的分隔线不一样

iphone - 当我把自己放进去时,NSArray 失去了值(value)

ios - 没有与键解析 json 关联的值

swiftui - 如何在 SwiftUI 的 View 中调用方法

ios - SwiftUI : Picker does not update correctly when changing datasource

SwiftUI:如何将 View 附加到多行文本的结尾?