00:00:07
大家好 我叫 Taylor
00:00:09
欢迎学习“SwiftUI 基础知识”
00:00:11
SwiftUI 是 Apple 的
声明式用户界面框架
00:00:14
用于开发适合
各个 Apple 平台的 App
00:00:18
这个框架已在 Apple 内部广泛采用
00:00:21
既用于全新 App 的开发
00:00:22
也逐步应用于现有 App
00:00:26
当你在开发新的 App
或新功能时
00:00:28
SwiftUI 是非常理想的工具
00:00:31
原因有几个
00:00:33
SwiftUI 提供了
丰富多样的功能
00:00:36
让你的 App 能够
充分利用所运行的设备
00:00:39
能在 Apple 的平台上提供
原生体验和丰富的交互功能
00:00:44
而且添加这些功能
需要编写的代码量更少
00:00:47
因此你能更快地
从原型过渡到生产环境
00:00:50
让你更专注于打造
App 的独特之处
00:00:54
SwiftUI 支持渐进式采用策略
00:00:58
这意味着你可以
根据需要灵活利用
00:01:02
我们并不要求整个 App
必须完全基于 SwiftUI
00:01:06
才能受益于它
00:01:08
这些特质让任何人
00:01:10
都能轻松学习如何
用 SwiftUI 构建 App
00:01:13
而理解 SwiftUI
如何实现这些特质
00:01:16
可以帮助你了解
如何最有效地利用这些特质
00:01:19
我将从最基础的内容入手
介绍一下
00:01:21
视图的工作原理
00:01:23
之后 我将着重介绍
SwiftUI 中内置的
00:01:25
一些功能
00:01:26
以及这些功能在
各种 Apple 平台上运作的方式
00:01:29
最后
00:01:30
我将探讨 SwiftUI
与其他框架集成的能力
00:01:35
但在开始之前
00:01:36
我想分享关于 SwiftUI
和背后团队的趣闻:
00:01:40
我们都非常喜欢自己的宠物
00:01:41
常常争论
哪种宠物最棒
00:01:44
为了公正解决这一问题
我决定采取最客观的方式
00:01:48
看看哪种宠物能表演最棒的技巧
00:01:52
这无疑是一场高手间的较量
00:01:56
在这个视频中
00:01:57
我将使用 SwiftUI 构建一款 App
用于记录我们的宠物、
00:02:00
它们学会的技巧及在竞争中的排名
00:02:03
但每个项目都有个起点
00:02:05
而在 SwiftUI 中
一切始于视图
00:02:09
视图是用户界面的
基本构建块
00:02:12
对于你在 SwiftUI 中
所做的一切至关重要
00:02:16
屏幕上显示的每个像素
都以某种方式由视图定义
00:02:20
SwiftUI 视图之所以特别
主要归功于三大特性:
00:02:24
声明式
00:02:25
组合性
00:02:26
和基于状态驱动
00:02:28
视图通过声明式方式表达
00:02:31
你只需描述希望
在用户界面中呈现什么样的视图
00:02:34
SwiftUI 就会自动生成相应效果
00:02:36
你可以创建文本、
00:02:38
含 SF Symbols 的图像
00:02:40
以及控件 比如按钮
00:02:43
这个代码创建了一个水平堆栈
其中包含一个由图标和标题
00:02:47
组合而成的标签
00:02:49
一个空白区域及末尾的文本
00:02:53
这种声明式语法
同样适用于其他容器
00:02:56
比如可滚动列表
00:02:59
当给定一个宠物集合时
00:03:01
此列表会为每种宠物
创建一个水平堆栈
00:03:04
鉴于不是每只宠物都叫 Whiskers
00:03:06
我将更新堆栈中的视图
改为使用每只宠物的属性
00:03:12
从始至终
我都不需要描述
00:03:14
生成这个 UI 所需的操作
00:03:16
比如向列表中
添加或删除行
00:03:19
这正是声明式编程
和命令式编程的区别所在
00:03:24
如果你
曾教过宠物做把戏
00:03:26
你对命令式指令应该相当熟悉
00:03:30
就像命令式编程一样
00:03:31
我可以一步步指示
这只叫 Rufus 的狗狗击出本垒打:
00:03:35
Rufus 过来
00:03:37
Rufus 拿球棒
00:03:38
Rufus 站到本垒板上
00:03:40
如此这般
逐一描述流程的每个步骤
00:03:44
相比之下
00:03:46
声明式宠物技巧
00:03:47
则是描述
你想要达成的结果
00:03:49
并让事先已训练好的小狗
为你完成
00:03:53
你只需说出你想要的:
看到 Rufus 打出全垒打
00:03:58
而且你可以
自定这个技巧的某些方面
00:04:00
比如让 Rufus 穿上定制的球服
00:04:04
声明式编程和命令式编程
并不互斥
00:04:09
声明式代码让你
专注于预期结果
00:04:12
而非达成目标的具体步骤
00:04:14
而命令式代码
则非常适合需要更改状态
00:04:18
或在没有现成的
声明式组件时使用
00:04:21
而 SwiftUI 支持这两种代码
00:04:23
按钮就是一个很好的例子
00:04:25
按钮以声明方式添加到用户界面
00:04:29
声明的一部分
是轻点时执行的操作
00:04:33
这个操作使用命令式代码
来实现状态的改变:
00:04:37
比如在这个示例中
向列表中添加新的宠物
00:04:41
SwiftUI 的视图是
00:04:43
对 UI 当前状态的描述
00:04:45
它们不是随时间推移
00:04:47
接收命令式指令的长期对象实例
00:04:50
因此 SwiftUI 视图是值类型
使用结构而不是类进行定义
00:04:56
SwiftUI 接收这些描述
00:04:58
并创建一个高效数据结构
来表示它们
00:05:01
它在后台维护这个数据结构
00:05:04
用于生成不同的输出
00:05:06
例如:屏幕上显示的内容
00:05:09
各种手势和视图的交互元素
00:05:11
及相关辅助功能呈现方式
00:05:14
由于视图
是声明式的描述
00:05:17
将一个视图拆分为多个视图
不会影响 App 的性能
00:05:21
在追求最佳性能的同时
你无需在代码组织方式上
00:05:22
做出让步
00:05:24
完全可以按自己的意愿去组织代码
00:05:26
组合在整个 SwiftUI 中广泛使用
00:05:29
是每个用户界面的
重要组成部分
00:05:32
我先前构建的 HStack
是一个用于布局的
00:05:35
容器视图
00:05:37
它将子项放置在水平堆栈中
00:05:40
在 SwiftUI 中重新排列
和试验容器视图
00:05:42
非常简单
00:05:45
代码本身类似于
它创建的视图层次结构
00:05:49
水平堆栈包含三个视图:
00:05:52
图像、垂直堆栈和空白区域
00:05:56
垂直堆栈自身又包含两个视图:
00:05:59
标签和文本
00:06:02
这种语法使用视图构建器闭包
来声明容器的子项
00:06:08
在这个示例中
我正在使用 HStack 的构造器
00:06:10
它使用了 ViewBuilder 内容参数
00:06:13
这是 SwiftUI 中
所有容器视图都使用的模式
00:06:17
组合在另一个 SwiftUI 模式中
发挥着重要的作用
00:06:20
即视图修饰符
00:06:23
视图修饰符把修改应用于基本视图
00:06:26
并可以更改这个视图的任何方面
00:06:29
我将用 Whiskers 的可爱照片来演示
00:06:32
首先将它裁剪成圆形
00:06:35
添加阴影
00:06:36
并在上面叠加绿色边框
那是它最喜欢的颜色
00:06:41
从语法上讲
这与容器视图有很大不同
00:06:44
但最终也会形成
类似的层次结构
00:06:47
效果的层次结构和顺序是
00:06:49
根据修饰符的确切顺序确定的
00:06:53
将修饰符串联起来
可以清晰地展示出结果是如何产生的
00:06:57
以及如何自定这个结果
00:06:59
所有这些都采用易于阅读的语法实现
00:07:02
视图层次结构可以封装到
自定视图和视图修饰符中
00:07:06
自定视图
遵照 View 协议
00:07:09
并使用 body 属性
来返回它所代表的视图
00:07:13
从 body 返回的视图
00:07:14
使用我到目前为止展示的
相同的视图构建语法
00:07:17
支持相同的组合特性和快速迭代
00:07:21
你可以创建其他视图属性
00:07:23
来帮助你根据需要组织代码
00:07:26
我已将头像结构重构为
00:07:29
一个私有的视图属性
00:07:32
通过这些循序渐进的步骤
00:07:34
我可以持续迭代
00:07:35
并构建出
完全符合需求的行视图
00:07:39
自定视图会接收改变 body
生成方式的输入
00:07:43
我已经为这一行将要表示的宠物
添加了一个属性
00:07:47
并在从 body 返回的视图
中使用了这个属性
00:07:51
通过这一改动
我可以重复使用相同的视图
00:07:53
来展示关于 Whiskers
00:07:55
以及 Roofus 和 Bubbles 的信息
00:07:58
自定视图与任何其他视图的
使用方式一样
00:08:01
在这里 我在列表中用
自定视图为每只宠物创建视图
00:08:06
列表非常有效地证明了
视图组合的强大
00:08:10
这个 List 构造器
使用集合参数
00:08:13
这为创建 ForEach 视图
提供了便利
00:08:16
ForEach 为集合中的
每个元素生成视图
00:08:20
并将这些视图提供给相应容器
00:08:22
这种基于视图的 List 构造器
支持创建
00:08:25
更高级的结构
00:08:27
比如将多个集合的数据
分到不同板块中
00:08:31
一个板块用于我的宠物
另一个用于他人的宠物
00:08:35
列表也可以借由视图修饰符
来实现定制化
00:08:39
例如
为每一行添加轻扫操作
00:08:43
通过更多容器和修饰符的组合
00:08:46
我可以循序渐进地
构建整个 App
00:08:50
SwiftUI 中的视图
的第三个特点
00:08:52
是基于状态驱动
00:08:54
当视图的状态随时间发生变化时
00:08:56
SwiftUI 会自动保持
UI 的最新状态
00:08:59
消除样板代码和更新错误
00:09:03
SwiftUI 在后台维护
00:09:05
用户界面的呈现
00:09:08
随着数据的变化
00:09:09
新的视图值被创建
并传给 SwiftUI
00:09:13
SwiftUI 会根据这些值来确定
如何更新它的输出
00:09:18
我的 App 现在列出了
宠物及技巧
00:09:21
但宠物比赛中
最重要的部分
00:09:23
是给我认为
掌握了最佳技巧的宠物颁发奖励
00:09:27
这是 Sheldon
00:09:28
它想获得的奖励是草莓
00:09:31
在为每行添加了滑动操作后
我已经做好了
00:09:33
充分的准备
00:09:35
当我轻点奖励按钮时
会调用响应操作
00:09:39
这个操作会修改关联的宠物对象
并将 hasAward 更改为 true
00:09:46
SwiftUI 会跟踪
所有依赖于这个宠物的任何视图
00:09:49
比如行视图
00:09:51
这里引用了相应的宠物
00:09:53
在 body 中读取
宠物是否获得奖励的信息
00:09:57
从而建立依赖项
00:10:00
随着宠物状态更新
SwiftUI 将再次调用这个视图的 body
00:10:04
它现在返回的结果中
会包含一张图像
00:10:06
以显示 Sheldon 获得的奖励
00:10:09
SwiftUI 根据这个结果
更新输出
00:10:12
从而在屏幕上显示新图像
00:10:15
视图在它的 body 中
使用的任何数据
00:10:18
都是这个视图的依赖项
00:10:21
在我的 App 中
我创建了一个可观察的宠物类
00:10:24
SwiftUI 能针对视图 body 中
所使用的特定属性
00:10:27
创建依赖项
00:10:30
SwiftUI 提供了几种用于
管理状态的工具
00:10:33
另外两个重要工具是
State 和 Binding
00:10:37
State 会为视图创建
新的内部数据源
00:10:41
使用 @State 标记视图属性后
00:10:43
SwiftUI 会管理这个属性的存储
00:10:45
并确保视图
能够读取和写入这个属性
00:10:49
Binding 则创建对其他一些
视图状态的双向引用
00:10:53
我编写了另一个
利用这些特性的视图
00:10:56
这个视图
让我可以给宠物的技巧打分
00:11:00
它使用 State
来跟踪当前评分
00:11:02
并持续更新评分
00:11:04
这个值会显示在
中间的显眼位置
00:11:07
并有两个按钮来
增加或减少值
00:11:12
SwiftUI 会在后台
维护这个状态的值
00:11:16
与前面的示例类似
轻点按钮就能调用响应操作
00:11:20
这一次
00:11:21
轻点操作增加了
视图内部的 State 值
00:11:25
SwiftUI 检测这一变化
并在 RatingView 上调用 body
00:11:28
这会返回一个新的文本值
00:11:31
更新后的结果随后显示在屏幕上
00:11:34
我将重点放在
body 中的视图部分
00:11:37
因为状态变化发生在这里
00:11:40
目前 更改会立即生效
00:11:43
没有伴随动画效果
00:11:45
SwiftUI 中的动画是
基于我之前提到的
00:11:48
数据驱动更新机制构建的
00:11:50
当我用 withAnimation 包裹
这个状态变化后
00:11:53
生成的视图更新
会带有默认的动画效果
00:11:58
SwiftUI 为文本
应用了默认的
00:12:00
淡入淡出过渡
00:12:02
但我也可以自定过渡效果
00:12:05
在这个示例中
00:12:06
数字文本内容过渡
是理想的选项
00:12:11
通过结合状态和动画效果
00:12:13
我构建了一个封装视图组件
它具备了我想要的互动效果
00:12:17
最终 我将在 App 的其余部分
都使用这个视图
00:12:21
这里是另一个视图
名为 RatingContainerView
00:12:25
它的 body 中包括 Gauge
和 RatingView
00:12:29
目前
每个视图都有各自的状态
00:12:32
作为自身的
00:12:34
评分来源
00:12:36
然而
00:12:37
这意味着当评分视图
自身状态增加时
00:12:40
容器视图的状态
和 Gauge 都不会随之改变
00:12:44
我已经更新了 RatingView
让它接受 Binding 作为输入
00:12:48
以便它的容器视图可以
提供双向引用
00:12:52
现在 容器视图的状态
成为了唯一的数据源
00:12:55
不仅向 Gauge 提供值
00:12:58
还为 RatingView 提供 Binding
00:13:00
这样三者就实现了同步更新
00:13:02
而且动画状态改变
也会应用于 Gauge
00:13:06
SwiftUI 提供了多个级别的
内置功能
00:13:09
为你构建 App
提供了更高的起点
00:13:14
我这个追踪宠物及技巧的 App
才刚刚起步
00:13:17
但我对目前的进展颇为满意
00:13:19
SwiftUI 自动提供
多个维度的自适应性
00:13:24
我的 App 在深色模式下效果不错
00:13:27
它支持多个辅助功能
00:13:29
比如动态类型
00:13:31
现在可以对它进行本地化了
00:13:33
比方说 我要用一种从右到左显示的
模拟语言来预览它
00:13:36
体验一下
希伯来语或阿拉伯语的展示效果
00:13:40
这是使用 Xcode 预览的好处之一
00:13:44
它能快速显示视图的外观
包括在不同环境中的效果
00:13:48
它会在你编写代码时显示效果
00:13:51
不需要一遍遍地运行 App
00:13:54
预览甚至在设备上
00:13:56
也是交互式的
00:13:58
在构建功能的同时
你可以确切了解到
00:14:01
正在开发的这个功能
00:14:02
能带来怎样的体验
00:14:04
SwiftUI 声明式视图的一大优势
在于自适应性
00:14:09
SwiftUI 提供的视图
通常描述功能意图
00:14:13
而不是
具体的视觉结构
00:14:16
之前我展示了如何用按钮等视图
组成轻扫操作
00:14:21
按钮就是自适应视图的
绝佳示例
00:14:24
它们有两个基本属性:
00:14:26
操作和描述操作的标签
00:14:30
它们可用于
许多不同的场景中
00:14:32
但始终承载着
所标记操作的核心功能
00:14:37
它们能适应不同的样式
00:14:39
例如无边框、带边框
或醒目显示
00:14:43
能自动根据不同的环境
进行调整
00:14:45
例如轻扫动作、菜单和表单
00:14:49
这个模式适用于
SwiftUI 中的所有控件
00:14:51
包括切换开关
00:14:54
切换开关有不同的样式
00:14:55
例如开关、复选框
和切换按钮
00:14:58
在不同的环境中
会以符合习惯的样式显示
00:15:01
用以表示
打开和关闭状态
00:15:06
SwiftUI 中的许多视图
都具有相同的自适应特性
00:15:10
利用组合来影响行为
00:15:13
并允许定制
00:15:15
某些视图修饰符
也同样如此
00:15:18
我最常用的示例之一是 searchable
我要将它应用于我的宠物列表
00:15:24
在添加 searchable 修饰符时
00:15:26
我描述的是
应用这个修饰符的视图
00:15:27
是可以进行搜索的
00:15:30
SwiftUI 会处理所有细节
并以符合习惯的方式实现这一功能
00:15:35
通过逐步采用
其他修饰符
00:15:38
你可以定制体验:
00:15:40
如添加建议、筛选范围
和关键词标记
00:15:45
SwiftUI 的声明式视图和自适应视图
00:15:48
只需几行代码即可
实现众多功能
00:15:52
其中包括各种控件
例如按钮、切换开关和选择器
00:15:56
NavigationSplitView 等容器视图
或可自定的多列表格
00:16:01
展示模式
例如模态窗口和检查器
00:16:05
以及文档中提供的
许多可供探索的其他示例
00:16:09
当你准备好打造
独特且个性化的用户体验时
00:16:13
SwiftUI 还为你准备了另一层的 API
提供更深层的控制支持
00:16:18
你可以打造自己的控件样式
00:16:20
使用 Canvas 进行高性能
命令式绘图
00:16:24
创建完全自定的布局
00:16:26
甚至直接在 SwiftUI 视图上
应用自定 Metal 着色器
00:16:31
在我的 App 中
记分牌就是
00:16:34
利用这些更深层工具
打造独特体验的理想位置
00:16:37
旨在重现经典的翻页板效果
00:16:40
我使用了动画、图形技巧
并巧妙融入了 Metal 着色器
00:16:46
Sheldon 在最后一个技巧中
没能完美落地
00:16:49
我只能给他打 7 分了
00:16:51
再接再励 伙计
00:16:54
SwiftUI 的功能
不仅限于视图
00:16:57
整个 App 的定义
都是基于与视图相同的原则
00:17:00
构建的
00:17:02
App 是由场景定义的
声明式结构
00:17:06
WindowGroup 是一种场景
00:17:08
它使用一种内容视图创建
以在屏幕上显示
00:17:12
不同的场景也可以组合
00:17:15
在 macOS 之类的
多窗口平台上
00:17:18
通过增设场景 用户能以多种方式
与 App 功能进行交互
00:17:23
这个模式同样适用于
构建自定小组件
00:17:26
小组件显示在
主屏幕和桌面上
00:17:29
并由视图组成
00:17:31
我重复使用了一些记分牌视图
来显示 Sheldon 的最新评分
00:17:36
SwiftUI 的功能可扩展到
它所运行的任何平台
00:17:40
使你能够把在一个平台上开发的成果
转换为
00:17:42
在其他平台上构建的原生 App
00:17:45
为任何 Apple 平台构建 App 时
都可以使用 SwiftUI
00:17:49
这能让你事半功倍:
00:17:52
只要使用 SwiftUI 为一个平台
构建用户界面之后
00:17:55
你可以水到渠成地
将这个 UI 移植到任何平台
00:17:59
我为 iOS 构建的 App
就是一个很好的例子
00:18:04
自适应视图和场景
可在任何 Apple 平台上
00:18:07
提供符合习惯的外观和风格
00:18:09
在 macOS 上
00:18:10
自动支持键盘导航
00:18:13
或创建多个窗口等功能
00:18:16
同样使用搜索建议
00:18:18
在 macOS 上会生成
标准下拉菜单
00:18:21
在 iOS 上会生成浮动列表
00:18:25
使用更深层的 API 自定制作的视图
00:18:28
在不同平台上
会产生相同的结果
00:18:30
这也是在需要时
重复使用相同视图的又一绝佳途径
00:18:35
我为完善记分牌动画
所做的工作
00:18:37
在所有平台上看起来都很棒
00:18:41
虽然 SwiftUI 通过这些方式
实现代码共享
00:18:43
但它并非编写一次就可用于所有平台
00:18:46
它是一套工具 你只需学习一次
00:18:49
就可以在任何环境
或任何 Apple 平台上使用
00:18:53
SwiftUI 提供一套在所有平台上
通用的高低层级组件集
00:18:58
但它也为每个平台提供了专门的 API
00:19:03
每个平台的使用方式
各不相同
00:19:06
因此设计方式也不一样
00:19:08
《人机界面指南》
介绍了组件、
00:19:11
模式
和平台的注意事项
00:19:15
NavigationSplitView 自动适应
watchOS 推送详细信息的
00:19:19
源列表设计
00:19:23
我重复使用了记分牌
这样的自定视图
00:19:26
但我想要针对 watchOS
做出一项更改
00:19:30
我希望能够使用数码表冠
00:19:32
来快速选择评分
而不是使用
00:19:34
触控或键盘
00:19:37
在相同的记分牌视图的基础上
00:19:39
我为 watchOS 额外添加了
一个修饰符:
00:19:42
digitalCrownRotation
00:19:45
现在当我转动数码表冠时
它会翻到我想要的分数
00:19:50
当我在 Mac 上查看宠物
和它们的技巧时
00:19:53
我想深入了解过去的数据
并比较各种宠物的数据
00:19:57
我可以在不同的
场景类型中利用
00:20:00
macOS 灵活的窗口模型
00:20:02
也可以使用能充分利用
macOS 熟悉的控件库、
00:20:06
信息密度和精确输入的视图
00:20:10
我还可以将 App 移植到 visionOS
00:20:12
利用其他平台的视图
00:20:14
并添加额外的立体内容
00:20:18
SwiftUI 助你打造在各个平台上
都表现出色的 App
00:20:21
这在本质上也是渐进式的
00:20:23
SwiftUI 不需要你
支持多个平台
00:20:26
但它为你准备好了
随时扩展的起点
00:20:30
最后一个方面不是
SwiftUI 本身的内置功能
00:20:33
但它体现了 SwiftUI 与其他框架的
00:20:35
功能进行互操作的能力
00:20:39
SwiftUI 是每个平台的
SDK 自带的框架
00:20:43
SDK 中还包括
许多其他框架
00:20:47
每个框架
各自拥有强大的功能
00:20:50
一个 App 不可能用到所有这些框架
00:20:52
但你可以从提供所需技术的
框架中进行选择
00:20:58
SwiftUI 为所有这些功能
提供了互操作性
00:21:01
在许多情况下
00:21:03
就像将另一个视图或属性
拖放到你的 App 中一样简单
00:21:08
UIKit 和 AppKit 是命令式的
面向对象的用户界面框架
00:21:13
它们都提供与 SwiftUI 类似的
构建块
00:21:16
但使用不同的模式
来创建和更新视图
00:21:20
它们还具备存在已久的丰富功能
SwiftUI 正是在这些基础上构建的
00:21:27
SwiftUI 的一个核心特性
是与它们的无缝互操作性
00:21:32
如果想要在 SwiftUI 中使用
UIKit 或 AppKit 中的
00:21:35
视图或视图控制器
你可以创建可表示视图
00:21:40
这是一种特殊的 SwiftUI 视图协议
00:21:42
用于使用命令式代码
创建和更新
00:21:46
关联的 UIKit 或 AppKit 视图
00:21:49
这将生成一个可以在 SwiftUI 的
声明式视图构建器中使用的视图
00:21:53
可以像任何其他视图一样使用
比如在 HStack 中使用
00:21:58
反之亦然
00:22:00
如果想将 SwiftUI 视图嵌入
UIKit 或 AppKit 视图层次结构中
00:22:04
你可以使用
Hosting View Controller 等类
00:22:07
这是使用根 SwiftUI 视图创建的
00:22:09
可以添加到 UIKit
或 AppKit 视图控制器层次结构中
00:22:14
Apple 自己的 App 使用这些工具
来逐步采用 SwiftUI
00:22:18
无论是将 SwiftUI
引入现有 App
00:22:21
还是在构建全新的 SwiftUI App
和整合 Kit 视图时
00:22:25
这些都是可供你用来
构建出色 App 的现成工具
00:22:30
我们并不要求整个 App
必须完全基于 SwiftUI
00:22:34
才能受益于它
00:22:37
SDK 中的每个框架
都各自具备独特的功能
00:22:41
SwiftData 使你能够快速
00:22:42
将持久性模型
添加到 App 中
00:22:45
并提供了 API
00:22:46
用于从你的 SwiftUI 视图
连接和查询这些模型
00:22:50
Swift Charts 是一个
高度可定制的图表框架
00:22:53
构建在 SwiftUI 之上
00:22:55
简化了创建
美观信息可视化效果的过程
00:23:00
所有这些框架
00:23:01
都可以用来帮助你
构建出色的 App
00:23:04
SwiftUI 是以声明式、组合性且
基于状态驱动的视图
00:23:07
为基础构建的
00:23:11
此外它还提供了
平台惯用的功能
00:23:14
以及与各种 SDK 的集成
00:23:17
所有这些都可以帮助你
集中精力打造 App 的独特之处
00:23:20
使用更少的代码
00:23:22
提供丰富多样的组件
用于打造符合习惯
00:23:25
且引人入胜的应用程序
00:23:27
同时支持渐进式采用
00:23:32
现在是时候
开始使用 SwiftUI 了
00:23:35
启动 Xcode
开始创建你的第一个 App
00:23:38
或开始将 SwiftUI
融入现有 App 中
00:23:42
查看更多关于 SwiftUI 的
精彩视频
00:23:44
接下来推荐观看
“Swift UI 简介”
00:23:48
跟随 SwiftUI 教程逐步学习
00:23:50
这些教程将指导你
构建不同的 App
00:23:53
文档中还有更多精彩内容
等待你探索
00:23:57
至于宠物比赛
00:23:59
要决定哪种宠物最棒
仅凭一个 App 怕是难以办到
00:24:03
目前我只能说
00:24:06
它们都是很棒的宠物