SwiftUI学习笔记day1—Stanford lecture1
- 课程链接:Lecture 1 | Stanford CS193p 2023
- 课程大纲:
- 代码仓库:github/iOS
文章目录
1.在Xcode中创建一个swiftUI的工程
首先你必须拥有一个apple id(最普通的apple id就可以,因为我们只是学习并不需要上架app)
打开Xcode的欢迎界面直接点击new project即可:
继续选择app:可以看到Xcode还可以创建其他类型的项目不过我们这里先创建一个app类型的工程
接下来有一些信息需要填写一下,以下是信息的含义和注意事项:
- Product Name:你要创建的应用名称,也会用于生成 Bundle Identifier。
- Team:选择你的开发者账号或个人团队,用于签名和发布应用。
- Organization Identifier:通常是反向域名格式,用来标识组织或个人,也会组合进 Bundle Identifier。
- Bundle Identifier:应用的唯一标识,和上架、签名紧密相关,不可随意更改。
- Testing System:指定测试框架(如 XCTest),可选择是否创建测试文件。
- Storage:设置项目存储位置,如本地或 Git 仓库。
注意:一旦正式发布到 App Store,Bundle Identifier 将不可更改,要事先规划好。
- 紧接着为你的工程选择一个合适的目录进行存储,之后点击create就会创建好一个工程了
2.简单认识Xcode这个IDE
其实我已经使用过一段时间的Xcode了,但是Xcode其实还有很多功能还没有用到,这里我用一张简短的视频表示Xcode目前我掌握到的功能以及一些细节:
3.尝试理解示例代码
- 示例代码和预览效果:
-下面我们对这段 SwiftUI 代码做一个非常详细、底层语法级别的解释,逐行剖析每个语法结构和细节。
- 模块导入
import SwiftUI
功能说明:
使用import SwiftUI
导入了 SwiftUI 框架。SwiftUI 是苹果提供的声明式 UI 框架,包含了大量用于构建用户界面的类型和工具。底层语法细节:
import
是 Swift 语言的关键字,用于引入模块(module),让代码能够使用该模块中定义的所有公共接口和类型。- 模块名称
SwiftUI
指定了需要加载的库,这样可以使用 SwiftUI 提供的视图、布局、控件和其他相关功能。
- 定义视图结构体
struct ContentView: View {
...
}
功能说明:
定义了一个名为ContentView
的结构体,并声明其遵循View
协议,从而成为一个可以被 SwiftUI 渲染的视图。底层语法细节:
struct
关键字定义了一个结构体(值类型),在 Swift 中结构体是一种常用的自定义数据类型。ContentView
是结构体的名称。命名时遵循大驼峰命名法。- 冒号
:
后面跟着的是一个协议名称View
。这意味着ContentView
必须满足View
协议的所有要求。 - Swift 中的协议(protocol)定义了一系列方法、属性或其他要求,
View
协议规定了一个视图必须实现的接口,最主要的是必须提供一个body
属性。
- 实现视图的主体
var body: some View {
VStack {
...
}
.padding()
}
功能说明:
- 定义了一个名为
body
的计算属性,它必须返回符合View
协议的内容。SwiftUI 使用该属性来确定如何绘制这个视图的界面。 - 使用了 Swift 的不透明返回类型(
some View
),表示返回值符合View
协议,但具体类型对调用者是隐藏的。
- 定义了一个名为
底层语法细节:
var
声明了一个变量属性。由于body
是只读计算属性(没有set
方法),它实际上表现得像常量。body
的类型被声明为some View
,其中some
关键字利用了 Swift 的不透明返回类型特性,允许隐藏具体的视图类型细节,只需要保证返回的内容满足View
协议即可。- 大括号
{ ... }
内部定义了该属性的计算逻辑,也就是返回值。Swift 中的计算属性不需要显式返回语句(如果只有一行表达式,可以省略return
)。
- 垂直堆叠视图(VStack)
VStack {
Image(systemName: "globe")
.imageScale(.large)
.foregroundStyle(.tint)
Text("Hello, world!")
}
功能说明:
VStack
是一种容器视图,用于将其子视图垂直排列。- 该容器中包含两个子视图:一个图像和一个文本。
底层语法细节:
VStack { ... }
使用了尾随闭包语法,这在 Swift 中非常常见,用于将一段代码块作为函数的参数传递。- 括号内的代码块定义了
VStack
的子视图。SwiftUI 内部使用视图构建器(ViewBuilder)机制,将闭包中的多个表达式组合成一个复合视图。
- Image 视图
Image(systemName: "globe")
.imageScale(.large)
.foregroundStyle(.tint)
功能说明:
- 使用
Image(systemName: "globe")
创建了一个系统符号图标,这里使用的是 SF Symbols 中的"globe"
图标。 - 随后通过链式调用了两个视图修饰符(modifiers):
.imageScale(.large)
和.foregroundStyle(.tint)
,分别调整图像的缩放比例和前景样式。
- 使用
底层语法细节:
- 构造函数调用:
Image(systemName: "globe")
是对Image
结构体的初始化调用,传入的参数systemName
是一个标签,用于查找对应的系统图标。
- 链式调用(Method Chaining):
.imageScale(.large)
调用返回一个经过修改的Image
实例。.large
是一个枚举值,用于指定图像的显示大小。.foregroundStyle(.tint)
应用前景颜色样式,这里使用.tint
表示使用当前环境中的主色调或强调色。
- 每个修饰符都是 SwiftUI 提供的函数,这些函数通常会返回一个新的视图实例,而不改变原有视图。这种设计符合 SwiftUI 的声明式编程和不可变性原则。
- 构造函数调用:
- Text 视图
Text("Hello, world!")
功能说明:
- 创建一个文本视图,显示字符串
"Hello, world!"
。
- 创建一个文本视图,显示字符串
底层语法细节:
Text
是 SwiftUI 中的一个结构体,用于在界面上渲染文本内容。- 构造函数直接传入一个字符串字面量。Swift 中的字符串是
String
类型,支持多种文本处理功能。 - 这里没有额外的修饰符,意味着文本使用默认样式显示。
- 应用修饰符到 VStack
.padding()
功能说明:
.padding()
是一个视图修饰符,作用是在VStack
外围添加默认的内边距,使其与其它视图之间保持一定的间隔。
底层语法细节:
- 这也是一个链式调用。修饰符会返回一个新的视图实例,其中包含了原始
VStack
的布局信息及额外的内边距效果。 - SwiftUI 的修饰符设计是函数式的,每个调用都是不可变操作,生成一个全新的视图描述。
- 这也是一个链式调用。修饰符会返回一个新的视图实例,其中包含了原始
- 预览代码
#Preview {
ContentView()
}
功能说明:
- 这段代码使用 SwiftUI 的预览功能,在 Xcode 中可以实时预览
ContentView
的界面效果。
- 这段代码使用 SwiftUI 的预览功能,在 Xcode 中可以实时预览
底层语法细节:
#Preview
是一个特殊的编译器指令或宏(具体细节可能会随 Xcode 版本变化),用于标记预览内容。- 花括号
{ ... }
内部包含一个表达式ContentView()
,这实际上是调用ContentView
结构体的默认初始化器生成一个视图实例。 - 与传统的
PreviewProvider
协议实现方式相比,这种写法更加简洁,符合 SwiftUI 追求声明式和直观的设计风格。
代码总结
模块导入与结构体定义:
使用import
导入 SwiftUI 模块,并定义了一个遵循View
协议的结构体ContentView
。计算属性和不透明返回类型:
body
属性使用some View
作为返回类型,隐藏了具体的实现类型,但确保返回内容符合View
协议。视图构建与尾随闭包:
使用VStack
将Image
和Text
视图垂直排列,通过尾随闭包语法简化代码结构。链式调用的修饰符:
图像和容器均通过链式调用应用了各自的修饰符,这种方式符合 SwiftUI 的函数式和不可变性设计。预览机制:
最后的#Preview
代码块为开发者提供了实时预览界面的能力,便于调试和视觉调整。
4.开始尝试修改代码完成一个卡片的ui代码
下面按照如下格式分步说明如何构建这段代码,并在每个步骤中附上相关代码片段,同时解释为什么这么写。
构建步骤
4.1 新建 CardView 结构体
操作说明:
在项目中创建一个新的 SwiftUI 视图文件,或者直接在 ContentView.swift 中添加一个新的结构体 CardView
。
代码片段:
struct CardView: View {
// 后续会在此添加属性和视图内容
var body: some View {
// 视图内容将在这里定义
Text("Card")
}
}
为什么这么写:
- 使用
struct
定义视图符合 SwiftUI 的声明式编程方式,结构体是轻量级且高效的。 - 遵循
View
协议意味着这个结构体可以作为一个 UI 组件被渲染和组合到其他视图中。
4.2添加 isFaceUp 属性
操作说明:
定义一个 Bool
类型的属性 isFaceUp
,初始值设为 false
。这样你可以根据需要设置卡片的正反面状态,方便后续控制卡片的显示内容。
代码片段:
struct CardView: View {
var isFaceUp: Bool = false // 默认显示背面
var body: some View {
// 后续会在这里构建视图内容
Text("Card")
}
}
为什么这么写:
- 通过属性
isFaceUp
可以动态控制视图的状态(正面或背面),让代码具有更高的可复用性和扩展性。 - 默认值设为
false
,使得当不传递参数时,卡片默认显示背面。
4.3使用 ZStack 构建层次结构
操作说明:
采用 ZStack
将多个图形元素叠加起来。根据 isFaceUp
的值决定显示哪种内容。
正面状态:
在 ZStack
内依次添加:
- 一个白色填充的圆角矩形
- 一个带边框的圆角矩形
- 一个显示表情符号 “👻” 的文本视图
背面状态:
只需添加一个圆角矩形即可。
代码片段:
struct CardView: View {
var isFaceUp: Bool = false
var body: some View {
ZStack {
if isFaceUp {
// 正面状态
RoundedRectangle(cornerRadius: 12)
.foregroundColor(.white) // 填充白色背景
RoundedRectangle(cornerRadius: 12)
.strokeBorder(lineWidth: 2) // 添加边框
Text("👻")
.font(.largeTitle) // 显示表情并设置为大号字体
} else {
// 背面状态
RoundedRectangle(cornerRadius: 12)
}
}
}
}
为什么这么写:
ZStack
允许多个视图层叠显示,适合构建需要背景、边框和内容叠加的卡片效果。- 使用条件语句
if isFaceUp { ... } else { ... }
根据状态选择性地展示正面或背面视图,符合声明式编程风格。 - 分层次添加视图使得代码逻辑清晰,每个部分只负责一项视觉效果。
4.4 应用全局修饰符
操作说明:
在 ZStack
外添加 .foregroundColor(.orange)
修饰符,使得未单独指定颜色的元素(如背面卡片)呈现橙色;同时添加 .padding()
,让卡片之间保持合适的间隔,防止界面过于紧凑。
代码片段:
struct CardView: View {
var isFaceUp: Bool = false
var body: some View {
ZStack {
if isFaceUp {
RoundedRectangle(cornerRadius: 12)
.foregroundColor(.white)
RoundedRectangle(cornerRadius: 12)
.strokeBorder(lineWidth: 2)
Text("👻")
.font(.largeTitle)
} else {
RoundedRectangle(cornerRadius: 12)
}
}
.foregroundColor(.orange) // 全局设置前景色为橙色
.padding() // 添加内边距
}
}
为什么这么写:
- 将
.foregroundColor(.orange)
放在ZStack
外面,能统一设定所有默认颜色为橙色,确保视觉统一性。 .padding()
提供足够的空间,使得卡片之间不会紧贴在一起,提高界面的美观性和可读性。
4.5 在 ContentView 中使用 CardView
操作说明:
在主视图 ContentView
中使用 HStack
水平排列多个 CardView
,其中可以传入不同的状态(例如第一个卡片显示正面)。
代码片段:
struct ContentView: View {
var body: some View {
HStack {
CardView(isFaceUp: true) // 第一个卡片显示正面
CardView() // 其他卡片显示背面
CardView()
CardView()
}
}
}
为什么这么写:
- 使用
HStack
可以将多个CardView
组件水平排列,直观地展示多张卡片效果。 - 为第一个卡片传入
isFaceUp: true
参数,示范如何根据需要自定义不同视图状态,便于后续扩展和交互。
4.6 添加预览代码
操作说明:
使用预览功能可以在 Xcode 的预览窗口中实时查看 ContentView
的界面效果,帮助开发者调试和调整 UI。
代码片段:
#Preview {
ContentView(true)
}
为什么这么写:
- 预览代码简洁明了,通过
#Preview
指令将ContentView()
包装,使得 Xcode 能自动加载和显示该视图的预览效果,提升开发效率。