本文是斯坦福大学 cs193p 公开课程第01集的相关笔记。

cs193p 课程介绍:

The lectures for the Spring 2023 version of Stanford University's course CS193p (Developing Applications for iOS using SwiftUI) were given in person but, unfortunately, were not video recorded. However, we did capture the laptop screen of the presentations and demos as well as the associated audio. You can watch these screen captures using the links below. You'll also find links to supporting material that was distributed to students during the quarter (homework, demo code, etc.).

cs193p 课程网址: https://cs193p.sites.stanford.edu/2023


创建新的iOS项目

选择 File -> New -> Project

"Hello World" 代码

完整的 "Hello World" 代码

struct ContentView: View {
    var body: some View {
        VStack {
            Image(systemName: "globe")
                .imageScale(.large)
                .foregroundStyle(.tint)
            Text("Hello, world!")
        }
        .padding()
    }
}

struct 和 View

struct ContentView: View {
      ...
      ...
}
  • struct 代表结构体,它是SwiftUI的核心。它可以包含变量和函数。Swift不是面向对象的编程语言,因此 struct 不是 class。它是函数式编程。
  • ContentView 是结构体的名称。
  • View 意味着 ContentView 结构体一个 View

var

struct ContentView: View {
    var body: some View {
            ...
            ...
    }
}
  • var 是一个变量的关键字,body 是变量名。其他变量可能如下所示:
var i: Int
var s: String

计算属性 (Computed Property)

让我们看看 body 中的内容:

    var body: some View {
        VStack {
            Image(systemName: "globe")
                .imageScale(.large)
                .foregroundStyle(.tint)
            Text("Hello, world!")
        }
        .padding()
    }
  • var body 是一个属性,body 变量的值不会存储在某个地方,而是在每次程序运行时都会计算一次。在 "Hello World" 代码中,它计算的是如下部分:
                                                {
        VStack {
            Image(systemName: "globe")
                .imageScale(.large)
                .foregroundStyle(.tint)
            Text("Hello, world!")
        }
        .padding()
    }

some ViewStringInt不同。它一定是某种类型的 View,但可以是不同类型的 View,只要它是一个 View 即可。

VStack

        VStack {
            Image(systemName: "globe")
                .imageScale(.large)
                .foregroundStyle(.tint)
            Text("Hello, world!")
        }
  • creating instance of structs:像图像结构体 Image(systemName: "globe");或文本结构体 Text("Hello, world!")
  • named parameters:systemName 是一个参数名。
  • Parameter defaults:还可以指定其他参数,但我们可以使用默认值。
  • 这个 VStack 有两个结构体,它们都像一个 View 一样。它包括 ImageText 结构体。但是,VStack 本身也是一个像 View 一样的结构体。我们可以为 VStack 提供参数,例如:
        VStack(alignment: .leading, spacing: 20) {
            Image(systemName: "globe")
                .imageScale(.large)
                .foregroundStyle(.tint)
            Text("Hello, world!")
        }
  • 那么 VStack 内部的整个内容呢?

    • 这是 VStack 的一个参数,完整内容应该如下所示:
        VStack(content: {
            Image(systemName: "globe")
                .imageScale(.large)
                .foregroundStyle(.tint)
            Text("Hello, world!")
        })
  • VStack 也被称为 @ViewBuilder。@ViewBuilder 可以将视图列表(Image、Text)转换为 TupleView。

View modifier

            Image(systemName: "globe")
                .imageScale(.large)
                .foregroundStyle(.tint)
  • .imageScale.foregroundStyle 称为 View modifier。View modifier 将值返回给 .imageScale,然后 .imageScale 也返回给 .foregroundStyle。因此,它们可以连接在一起。

View modifier 的作用域

视图修改器的作用域很重要。如果作用域不同,将显示不同。

view-modifier-scope-1

▲ 作用域 1

view-modifier-scope-2

▲ 作用域 2

开始创建卡片

a-single-card

▲ 创建一个带有白色背景的单张卡片

four-cards

▲ 创建4张卡片

import SwiftUI

struct ContentView: View {
    var body: some View {
        HStack {
            CardView(isFaceUp: true)
            CardView()
            CardView()
            CardView()
        }
        .foregroundColor(.orange)
        .padding()
    }
}

struct CardView: View {
    var isFaceUp: Bool = false
    var body: some View {
        ZStack(content: {
            if isFaceUp {
                RoundedRectangle(cornerRadius: 12)
                    .foregroundColor(.white)
                RoundedRectangle(cornerRadius: 12)
                    .strokeBorder(lineWidth: 2)
                Text("👻").font(.largeTitle)
            } else {
                RoundedRectangle(cornerRadius: 12)
            }
        })
    }
}

#Preview {
    ContentView()
}

four-cards-can-control-face-up-and-down

▲ 创建4张卡片,并带有一个可以控制卡片正反面的参数

注意:每个 变量(var) 必须有一个值,但我们可以设置一个默认值。