大多数浏览器和
Developer App 均支持流媒体播放。
-
Swift 的新功能
和我们一起了解有关 Swift 的最新更新。我们将简要介绍 Swift 过去十年的发展历程,并带你了解 Swift 社区如何通过设立工作组、扩充软件包生态系统以及增强平台支持来不断发展壮大。我们还将介绍一种默认情况下可实现数据争用安全性的新语言模式,和一个可让你在高度受限系统中运行 Swift 的语言子集。此外,我们还将探索一些语言方面的更新,包括不可拷贝的类型、类型化的抛出,以及更出色的 C++ 互操作性。
章节
- 0:00 - Introduction
- 0:12 - Swift over the years
- 3:44 - Agenda
- 3:58 - Swift project update
- 4:08 - Community
- 4:59 - Packages
- 5:50 - Blogs
- 6:33 - Swift everywhere
- 7:37 - Cross compilation to Linux
- 11:27 - Foundation
- 13:06 - Swift Testing
- 14:34 - Improvements to builds
- 16:15 - Swift's new space
- 17:03 - Language updates
- 17:29 - Noncopyable types
- 19:55 - Embedded Swift
- 21:47 - C++ interoperability
- 23:34 - Typed throws
- 26:07 - Swift 6 language mode and data-race safety
- 28:43 - Low-level synchronization primitives
- 29:59 - Wrap up
资源
- Forum: Programming Languages
- Install Swift
- Swift 6 Migration Guide
- Swift Blog
- Swift Community Overview
- Swift Forums
- The Swift Programming Language
相关视频
WWDC24
- 了解 Swift Testing
- 利用 Embedded Swift 实现轻量级开发
- 利用 Swift Testing 进一步优化测试
- 在 Swift 中使用不可拷贝的类型
- 将 App 迁移到 Swift 6
- 探索 Swift 性能
- 揭秘显式构建的模块
WWDC23
-
下载
大家好!欢迎观看 “Swift 的新功能”讲座 我叫 Mishal 稍后我的同事 Meghana 也将和我一起进行演示 今年是 Swift 项目的 一个重要里程碑 自从在 WWDC2014 上 发布以来 这个项目距今已有 10 年
在发布后的第二年 Swift 便推出了 开源版并可在 Linux 上使用 我们还针对 语言和标准资料库 推行了由社区驱动的 演变过程 2016 年 我们发布了 Swift Package Manager 以及 Swift 3 这是首个使用 新演变过程的语言版本 其中包含了 80 多个语言建议 如果你和我们一起经历了 从 Swift 2 迁移到 3 的过程 那么可能还记得 这一过程颇具挑战性 我们从中吸取了经验教训 到了 Swift 4 我们弄清楚了如何 引入一种新的语言模式 而无需将 所有的 Swift 代码一次性迁移过去 同一个编译器可以 支持多种语言模式 因此你可以在同一个程序中 自由搭配使用以 Swift 3 和 Swift 4 编译的模块 采用这种新方法 就能在整个生态系统中 逐步采用 新的语言模式 因此每个开发者都可以 在准备就绪后再迁移 2018 年 我们对泛型系统 进行了改进 比如我们如今在 Swift 中 认为理所当然的条件一致性 这也为我们最重要的 版本之一奠定了基础 在 Swift 5 中 我们推出了 Apple 平台上的稳定 ABI 对于 App 开发者来说 这意味着减小了下载大小 因为你不再需要 在 App 中捆绑 Swift 标准资料库的完整副本 相反 Swift 标准资料库 成为了操作系统本身的一部分 并且针对相应操作系统进行了优化 并在所有 Swift App 和框架中共享 这标志着一场根本性的转变 因为现在我们可以充分利用 Swift 的表现力来构建更出色 更安全的 API 和框架 而且我们确实做到了 我们推出了 SwiftUI 它可利用 Swift 的独特功能 更出色、更快速地构建 UI App 到 2020 年 Swift 已登陆更多平台 面向 Windows 平台的社区移植版本 也在 swift.org 上正式发布 2021 年 我们推出了一项重要功能 即并发模型 它具有 Async/Await、 Actor 和结构化并发
2022 年 我们又推出了 Distributed Actors 这使得构建网络服务 变得更加轻松 我们还继续 优化了并发模型 同年 社区发布了 适用于 VSCode 的 Swift 扩展 从而为 Swift 开发提供了 跨平台编辑体验
去年 我们推出了与 C++ 的 双向互操作性 从而可以更轻松地兼顾 Swift 的安全性和表现力 以改进大型跨平台 C++ 代码库 我们还推出了宏 帮助减少了重复的样板代码 并启用了像 SwiftData 这样 表现力更出色的新一代 API
接下来就到了 Swift 6 Swift 6 提升了 可移植性、性能 以及整体开发者体验 还引入了 Swift 6 语言模式 可提供数据争用安全保障 从而帮助你编写 正确的并发程序
我们将介绍 Swift 项目中的 一些关键成就和新投资 还将介绍 Swift 的 一些新应用领域 并且谈谈 一些新的语言功能 包括新的语言模式 Swift 6 Swift 编程语言 属于一个规模更大的生态系统 其中包含工具、软件包 以及充满活力的社区 里面有像你一样的开发者 下面我们来谈一谈 社区的发展历程 最初 Swift Core 团队 是唯一的指导小组 负责语言演变过程 等事宜 随着社区不断发展壮大 我们在过去几年中 扩充了指导小组 和工作组的数量 今年 我们设立了 平台指导小组 专注于将 Swift 应用于更多领域 此外 Swift Core 团队 还积极致力于打造新的 生态系统指导小组 以专注于开发者体验 以及更广泛的生态系统 为延续底层环境的 这一发展势头 Swift Core 团队 还在致力于引入一个新的 嵌入式工作组 欢迎大家 加入 Swift 社区 在 swift.org/community 上 探索不同的指导小组 和工作组 Swift.org 是 Swift 项目的大本营 网站工作组 对主页和入门指南 做出了重大改进 这些指南现在包含各种新教程 其中包括跨平台资料库 和网络服务 旨在帮助你 探索 Swift 中的不同技术 要探索 Swift 软件包 现在可以访问 swift.org/packages 这个网站与 swiftPackageIndex.com 实现了整合 Swift Package Index 针对多个 Swift 版本和平台 构建了所有软件包 能帮助你为应用程序 选择合适的软件包 Swift 社区每个月都会提名软件包 入选 Community Showcase 如果你想提名 最喜爱的软件包 欢迎在 forums.swift.org 告知我们 今年的 swift.org 博客文章 着重展示了整个 Swift 社区 令人振奋的开发成果 下面举几个例子 The Browser Company 能够利用 Swift 的互操作性来构建 使用原生 UI 的 Windows App 博客文章“Writing GNOME Apps with Swift”介绍了结果构建器 如何为原生 GNOME UI 资料库 启用了声明式语法 这篇文章还介绍了 Swift 6 中的 一项全新功能 即 Pack 迭代 Pack 迭代简化了 与值参数包 交互的流程 例如 利用 Pack 迭代 可以针对任意长度的元组 轻松实现相等性运算符 Swift 作为一种跨平台语言 继续发展壮大 正在被移植到 越来越多的平台上 官方支持 Swift 的平台包括 Apple 平台、Linux 和 Windows 此外 Swift 社区 还推出了很多平台 包括 WebAssembly
今年 我们会将支持的 Linux 平台 扩展到涵盖 Fedora 和 Debian
Xcode 从一开始就一直是 Swift 的主要 IDE 现在仍然用于 开发 Apple 平台上的 App 但由于存在许多 不同的开发环境 所以我们开发了 SourceKit LSP 这是适用于 Swift 的 语言服务器实现 可以让 IDE 和编辑器整合 Swift 支持 很高兴看到社区已经在 VSCode、Neovim、Emacs 等编辑器中 采用了 sourcekit-lsp
这样 你就可以更轻松地 在自己选择的 编辑器和平台上 进行开发 交叉编译是 常见的开发用例 如果你一直在为 Apple 平台从事开发工作 你就已经在使用交叉编译了 通过交叉编译 你可以在一个环境中 生成一个可执行文件 然后在另一个环境中运行这个文件 例如 你可以在 macOS 上 构建 App 然后在 iPad 上运行它 现在我们想将 这一功能引入 Linux 这意味着你可以在熟悉的 macOS 环境上进行开发 然后将程序部署到 Linux 服务器或容器
我们很高兴推出适用于 Swift 的全静态 Linux SDK 以帮助你从 macOS 到 Linux 进行交叉编译 通过静态链接资料库 你将不再需要 为了运行程序而安装 额外的软件包 来看看这项功能的实际效果 我们将使用 Swift 软件包 其中包含简单的 REST API 用于随机返回一个猫脸表情符号 如果你想详细了解 这个软件包 请观看 “认识 Swift OpenAPI Generator” 我们将在 macOS 上构建这个软件包 并使用静态 Linux SDK 将它部署到 Linux 服务器上 我打开了三个终端窗口 左侧这个窗口 用于构建 Swift 软件包 这个终端已登录到我的本地机器 并且运行 macOS 右上角的终端也已 登录到我的 macOS 本地机器 它下面的这个终端显示的是 到 Linux 主机的开放 SSH 连接 首先 我将针对 macOS 构建服务 这可以通过运行 swift build 实现
生成的二进制文件 是为在 macOS 上运行而构建的 我们可以通过检查 构建输出来进行查看
接下来 通过右上角的终端 在我的本地机器上运行这项服务
现在我们可以向在 localhost 上 侦听的服务器发出请求 并查看记录这个请求的 本地服务器
下面我们来交叉编译这项服务 以便在 Linux 服务器上运行它 首先 我需要安装 适用于 Swift 的全静态 Linux SDK
安装这个 SDK 的同时 我们来 检查一下进行交叉编译所需的标志 swift-sdk 标志用于标识 构建所依据的 SDK 这里我们指定了 要针对 ARM64 Linux 环境 进行编译 并针对 musl 进行链接 以生成可在任何 Linux 机器上 运行的静态链接的二进制文件 即使机器没有安装 Swift 运行时也没问题 将这个标志添加到 swift build 命令并开始构建
这一次 生成的二进制文件 为在 Linux 上运行而构建 我们可以通过检查 构建输出来进行查看
我们将这段代码拷贝到 Linux 服务器上并运行!
现在我们可以从 Mac 向 Linux 服务器发出请求
成功了 我们得到了猫脸表情符号!
我们首先在 macOS 上 为 macOS 主机创建了服务 然后使用了适用于 Swift 的 全静态 Linux SDK 以进行从 macOS 到 Linux 主机的 交叉编译 这样我们就能生成一个 可在任何 Linux 机器上运行的 静态链接的二进制文件 而无需安装 额外的运行时 你可以从 swift.org/install 下载 SDK 预览版 下面我们来深入了解一下 Swift 中的一些关键资料库 Foundation 是众多应用程序的 基本组成部分 提供了重要的 API 其中包括 JSON 解码、日期和时间格式设置 以及文件系统操作等 它也是我们 历史最悠久的框架之一 历史可以追溯到 macOS X 诞生之初 当 Swift 进行开源时 我们就知道这个 API 将在所有平台上都有用 因此我们推出了 swift-corelibs-foundation 项目 从那之后 这门语言不断发展 让我们如今能够 在所有平台上使用 单个的统一实现 这就是我们为何将 Foundation 从旧式 C 和 Objective-C 重写为现代可移植的 Swift 得到的结果更加一致 质量更高 性能也更出色 新功能和新改进会同时 应用于所有受支持的平台 就像 Swift 本身一样 这一 Swift 实现于去年秋季 在 iOS 和 macOS 上率先发布 甚至 Objective-C 应用程序 也受益于这些改进 更棒的是 swift-foundation 是开源的 我们鼓励社区做出贡献 并制定了一个 用于添加新 API 的 开放式演变过程 例如 Predicate 是一个 API 现可通过 swift-foundation 在 Swift 6 中的所有平台上可用 今年 它还能支持 正则表达式 我们对 Foundation 的 这个新方向充满期待 因为它既有新的实现 又能与社区密切互动 下面我们来讨论一个新框架 Swift Testing 它简单易学、表现力强 灵活且可伸缩 它利用了宏等 现代 Swift 功能 并与并发功能 无缝整合 这个软件包以开源方式开发 兼顾了跨平台服务 它旨在无缝整合到 多个 IDE 中 比如 Xcode 和 VSCode Swift Testing 资料库的愿景是 成为生态系统的官方 默认测试解决方案 你可以在 Swift 演变愿景文档中 了解完整的 API 发展方向 下面来探讨一下 Swift Testing 的一些功能 要声明测试 需要向函数添加 Test 属性 你可以提供一个自定显示名称 作为 Test 属性的参数 这有助于更轻松地 了解测试的内容是什么 你可以使用 expect 来验证结果是否符合预期 这是一个宏 因此你可以编写 一个简单或复杂的 Swift 表达式 Swift Testing 让你可以 使用 tags 来管理和筛选测试 你可以使用 arguments 来避免 对多个输入重复执行相同测试 这里只重点介绍了 Swift Testing 的部分功能 如果你想了解更多功能 请观看视频“了解 Swift Testing” 和“利用 Swift Testing 进一步优化测试” 要测试代码 你需要先构建代码 所以我们改进了 Xcode 构建代码的方式 构建 Swift 代码时 每个模块都依赖于其他模块 通常是 SDK 中的模块 当 Swift 编译器 遇到 SwiftUI 这类的模块时 可能需要构建 这类模块的二进制版本 这是隐式发生的 你可能根本不会注意到 除非出现一次性减速 但这也隐藏了大量工作 因为它必须依次构建 使用的每个模块 包括用 Objective-C 或 C++ 编写的模块 在构建另一个 Swift 模块时 它将重复使用相同的二进制模块 但可能需要 等到它们准备就绪 这意味着我们无法从构建中 获得想要的并行性 此外 调试器可能必须针对 所有这些模块文件构建自己的版本 这可能导致调试器在 首次打印变量时 出现长时间停顿 显式构建的模块将 这些隐式步骤变成了显式构建步骤 这意味着可以 并行执行模块构建 而且它们会清晰显示在 构建日志中 因此构建更易于预测 并且更为可靠 调试器现在可以 与构建共享二进制模块 从而加快调试速度
可以在 Xcode 构建设置中 启用显式模块构建 如需了解更多信息 请观看“揭秘显式构建的模块”
在过去 10 年里 Swift 得到了长足的发展 获得了新的支持者 也经历了一些独特的体验 现在是时候进入 它自己的空间了 Swift 将迁移到 github.com/swiftlang 上的一个新组织 并将由 Swift Project 管理 这将包括 Swift 编译器、Foundation 以及 很多其他 Swift 生态系统软件包 我们很快就会开始迁移并在 swift.org 上发布相关详细信息 我们期待看到 Swift 在新的空间里不断发展壮大 感谢大家为这个语言 和生态系统的发展做出贡献 这仅仅是个开始 下面有请 Meghana 给大家详细介绍 Swift 6 中 出色的新语言功能 对于 Swift 来说 今年是非凡的一年 Swift 6 引入了一种可实现 数据争用安全性的新语言模式 从而将 Swift 的安全保障 扩展到了并发程序 我们还有一个名为 “Embedded Swift”的新语言子集 可在高度受限的 系统上运行 此外 Swift 6 还有多项新的改进 助力 Swift 变得更为出色 我们先来了解一下 不可拷贝的类型 所有 Swift 类型 无论是值类型 还是引用类型 默认情况下都是可拷贝的 不可拷贝的类型会禁止 这种默认可拷贝性 这使得它们适用于 你想表达 独特所有权的场景 例如 文件等 独特的系统资源 可以表示为不可拷贝的结构体 并带有自动 关闭它的析构器 这种表示形式 可防止运行时问题 例如多次写入同一个文件 它还可以防止 在没有自动清理的情况下 很容易引起的资源泄漏 不过 这种表示形式 仍然不够理想 构造器会接受 打开的文件描述符 这既不直观也不安全
你可能会在打开文件 和初始化之间引入一些代码 这会终止程序 析构器永远无法运行 从而导致资源泄漏 我们可以使用 可失败构造器来解决这个问题 这个构造器会接受文件名 打开文件 并在文件名有效的情况下 完成初始化 这个构造器会返回 不可拷贝的文件类型“Optional” “Optional”是标准资料库中的 泛型类型 Swift 5.10 对不可拷贝的 类型的支持仅限于具体类型 Swift 6 在所有泛型上下文 和标准资料库的“Optional”等 关键泛型类型中 引入了对不可拷贝的 类型的支持 有了这一支持 你现在可以编写 不可拷贝的类型的可失败构造器 比如文件类型 对可拷贝的 和不可拷贝的类型 进行泛型抽象这一强大功能 扩展了不可拷贝的类型 的可用性 如需了解更多信息 请观看“在 Swift 中使用不可拷贝的类型” 除了表达独特所有权 不可拷贝的类型 还让你可以精细地控制性能 在资源严重受限的 底层系统中 拷贝成本 有可能变得过高 因此这种情况也适合使用 不可拷贝的类型 底层系统在内存、 存储和运行时功能方面 受到限制 由于它们的占用空间小 C 和 C++ 一直是在这类系统上 进行编程的首选 现在 你可以使用 Swift Embedded Swift 是 Swift 的 新语言子集和编译模型 它可以生成非常小的 独立二进制文件 适用于高度受限的系统 它会关闭某些 需要运行时支持的语言功能 比如反射和“any”类型 并使用编译技术 比如全泛型特化 和静态链接 来生成合适的二进制文件 尽管关闭了 一些语言功能 但 Embedded Swift 子集 感觉还是非常接近“完整版”Swift 让你可以轻松继续编写 惯用且易读的 Swift 代码
借助 Embedded Swift 采用 Swift 编写的游戏现在可以 在小型游戏机上运行 例如 Playdate 游戏的二进制文件大小 只有几千字节! 但 Embedded Swift 不仅仅用于娱乐和游戏 它可以在用于 构建工业应用程序的 各种热门 ARM 和 RISC-V 微控制器上使用 Apple 安全隔区处理器 就使用了 Embedded Swift 安全隔区 是独立于主处理器的 独立子系统 专门用于保护敏感数据的安全
安全性在这类系统中至关重要 而 Embedded Swift 正为它们 提供 Swift 的安全保障 借助 Swift 与 C 和 C++ 的 互操作性 你可以在嵌入式项目中 逐步采用 Swift 如需了解更多信息 请观看 “利用 Embedded Swift 实现轻量级开发”
去年 我们推出了与 C++ 的 双向互操作性 Swift 可以直接与 C++ 进行互操作 从而提供无缝的 开发者体验和零桥接成本 我们一直在不断扩充 可互操作的语言功能 借助 Swift 6 C++ 虚方法、 默认参数、move-only 类型 以及关键的 C++ 标准资料库类型 都可以直接导入 Swift 中 互操作性涉及 映射类似的语言概念 并做出必要调整 以匹配语义 C++ 虚方法和默认参数 会映射到各自的 Swift 版本 C++ move-only 类型 例如 Person 类型 会映射到 Swift 中不可拷贝的类型 Swift 编译器 会在需要时插入 对 C++ move 构造函数的调用 如果你意外尝试拷贝 不可拷贝的值 Swift 编译器 会为你诊断出来 C++ 是一种使用广泛的 编程语言 但它缺乏安全保障 因此容易受到安全攻击 你可以在 C++ 项目中 逐步采用 Swift 并提高安全性 和工作效率 在 Mac 上 “访达” 现在也利用 C++ 互操作性 The Browser Company 使用它 在 Windows 上推出了 ARC 浏览器 Swift Godot 用它来提供 Swift 与 Godot 游戏引擎的绑定 C++ 是一门大型语言 与它的互操作性也在不断发展 请访问 swift.org 及时了解最新动态 如需进一步了解 C++ 互操作性 请观看去年发布的“融合 Swift 和 C++” Swift 提供出色的 错误处理支持 可在代码遇到异常情况时 抛出、传播和捕获错误 错误遵从错误协议 你可以使用 throws 关键字 编写抛出错误的函数 抛出的错误会进行类型擦除 并以“any Error”类型 显示在 catch 处理程序中 由于类型擦除会丢失 错误的具体类型信息 因此你可能需要 插入动态类型检查 在极少数情况下 还需要彻底处理错误 类型擦除还涉及 装箱和拆箱 在不具备运行时分配功能的 高度受限系统中 这带来了一项挑战 Swift 6 推出了类型化抛出 来解决这项挑战 类型化抛出 让你可以指定错误类型 以及 throws 关键词 这并不涉及类型擦除 而且错误会显示在 带有具体类型的捕获块中 类型化抛出是对我们 现有的错误处理系统的泛化 非类型化的抛出与类型为 “any Error”的类型化抛出相同 非抛出函数也与 具有类型为“Never”的 类型化抛出的函数相同 这种由类型化抛出 引入的表达方式 让你能够以通用的方式 处理错误类型 例如 map 函数 接受一个可能抛出的闭包 然后将闭包映射到它的元素上 通过类型化抛出 map 函数可以 针对 Failure 类型进行泛型编写 从而针对抛出和非抛出情况 进行抽象处理 这样可以避免代码重复 并指定精确的 API 协定 由于类型化的抛出会指定 API 协定中的 Failure 类型 因此它制约了 API 的发展 如果你想保持更改 抛出错误类型的灵活性 请继续使用非类型化抛出 以下情况使用类型化抛出 使用内部函数 或者函数 通过它的参数传播错误 或者是在 受限环境中工作 因为在上述情况下 使用非类型化抛出的成本过高
除了我们提到的 类型化抛出和其他更新外 Swift 6 编译器还对语言 进行了其他几项改进 并在内部提升了 性能和稳定性 除此之外 Swift 6 编译器还发布了 一种默认情况下可实现 数据争用安全性的新语言模式 数据争用是编写并发程序时的 一种常见的编程错误 当多个线程共享数据 而其中一个线程试图更改数据时 可能就会出现这种错误 数据争用可能导致 意外的运行时行为、 程序崩溃 和难以重现的问题 从一开始 数据争用安全保障 就一直是 Swift 并发的主要目标 我们也一直在 朝着这个目标逐步迈进 Swift 并发的设计围绕 实现数据隔离的机制、 用于保护可变状态的 Actor 以及 用于实现安全数据共享的 Sendable Swift 5.10 借助完整并发检查标志 实现了数据争用安全性 新发布的 Swift 6 语言模式 默认提供数据争用安全保障 将 App 中的所有数据争用问题 转变为编译时错误 大幅提高 App 的安全性 减少关键时刻的 调试冒险 由于你可能需要使用新语言模式 对代码进行调整 因此可以在准备就绪后再采用它 你可以逐个模块采用 Swift 6 语言模式 甚至可与可能已迁移到 或尚未迁移到这个语言模式的 依赖项进行互操作 数据争用安全保障 是启用 Swift 6 语言模式后 所管辖的唯一更新 当你更新到 Swift 6 编译器后 所有其他更新都默认可用 我们还对数据争用检查 进行了重大改进 为确保安全性 Swift 5.10 中的完整并发检查 禁止跨越 Actor 隔离边界 传递所有非 Sendable 的值 Swift 6 可以识别出 在非 Sendable 的值无法再从 原始隔离边界进行引用的情况下 传递它们是安全的 例如 如果使用 Swift5.10 的 完整并发检查 将非 Sendable 客户端引用 从 MainActor 传递到 ClientStore Actor 将会导致编译器警告 但客户端引用被发送到 ClientStore Actor 之后 就不会 再被 MainActor 引用了 由于客户端的状态 不会在 MainActor 和 ClientStore Actor 之间进行共享 因此不会存在数据争用 随着 Swift 6 中 对数据争用检查的改进 这段代码可以成功编译 如果你在把客户端引用传递给 ClientStoreActor 之后又将它引入 编译器将会发出错误 表明发生了数据争用 除了 Actor 提供的 高级同步模型 Swift 6 还包含一些 新的底层原语 同步模块 引入了 Atomic 它们对于 在平台上提供 高效无锁实现的 任何类型来说都是通用的 应始终将 Atomic 的值 储存在“let”属性中 以实现安全的并发访问 对 Atomic 的所有操作都是些显式的 采用类似于 C 和 C++ 内存模型的内存排序参数 同步模块 还引入了 Mutex 与 Atomic 一样 Mutex 也应该 存储在“let”属性中 并可以安全地进行并发访问 对由 Mutex 保护的存储 进行的所有访问 都是通过传递给 withLock 方法的闭包进行的 从而确保实现互斥访问
有了用于增量迁移的基础架构、 改进的数据争用检查 以及用于同步的 新的底层原语 我们已经构建了 实现数据争用安全性所需的所有工具 关于迁移的最佳做法 可以参照“将 App 迁移到 Swift 6”中的实际操作教程 从新的和改进的语言功能 到宝贵的安全保障 再到利用 Swift 的新途径 我们今天介绍了很多内容 欢迎在 swift.org 上加入我们 携手打造 Swift 的下一个十年 感谢观看 祝大家编码愉快!
-
-
9:15 - Swift Build
swift build
-
9:20 - Inspecting the build output
file .build/debug/CatService
-
9:24 - Run the REST API service
.build/debug/CatService
-
9:30 - Make a request to REST API service
curl localhost:8080/api/emoji
-
9:45 - Install the Fully static Linux SDK for Swift
swift sdk install ~/preview-static-swift-linux-0.0.1.tar.gz
-
10:18 - Swift build command flag to cross compile
swift build --swift-sdk aarch64-swift-linux-musl
-
10:30 - Inspecting the build output
file .build/debug/CatService
-
10:35 - Copy the service over to our Linux server and run it
scp .build/debug/CatService demo-linux-host:~/CatService ./CatService
-
10:45 - Make a request to REST API service from macOS to Linux
curl demo-linux-host:8080/api/emoji
-
13:50 - Swift Testing - Declare a test function
// Swift Testing import Testing @Test func rating() { let video = Video(id: 2, name: "Mystery Creek") #expect(video.rating == "⭐️⭐️⭐️⭐️") }
-
13:55 - Swift Testing - Customize a test’s name
// Swift Testing import Testing @Test("Recognized rating") func rating() { let video = Video(id: 2, name: "Mystery Creek") #expect(video.rating == "⭐️⭐️⭐️⭐️") }
-
14:13 - Swift Testing - Organize test function with tags
// Swift Testing import Testing @Test("Recognized rating", .tags(.critical)) func rating() { let video = Video(id: 2, name: "Mystery Creek") #expect(video.rating == "⭐️⭐️⭐️⭐️") }
-
14:19 - Swift Testing - Parameterize test with arguments
// Swift Testing import Testing @Test("Recognized rating", .tags(.critical), arguments: [ (1, "A Beach", "⭐️⭐️⭐️⭐️⭐️"), (2, "Mystery Creek", "⭐️⭐️⭐️⭐️"), ]) func rating(videoId: Int, videoName: String, expectedRating: String) { let video = Video(id: videoId, name: videoName) #expect(video.rating == expectedRating) }
-
17:50 - Noncopyable types
struct File: ~Copyable { private let fd: CInt init(descriptor: CInt) { self.fd = descriptor } func write(buffer: [UInt8]) { // ... } deinit { close(fd) } }
-
18:12 - Noncopyable types
guard let fd = open(name) else { return } let file = File(descriptor: fd) file.write(buffer: data)
-
18:42 - Noncopyable types
struct File: ~Copyable { private let fd: CInt init?(name: String) { guard let fd = open(name) else { return nil } self.fd = fd } func write(buffer: [UInt8]) { // ... } deinit { close(fd) } }
-
22:29 - C++ Interoperability
struct Person { Person(const Person&) = delete; Person(Person &&) = default; // ... };
-
22:34 - C++ Interoperability
struct Developer: ~Copyable { let person: Person init(person: consuming Person) { self.person = person } } let person = Person() let developer = Developer(person: person)
-
22:40 - C++ Interoperability
struct Developer: ~Copyable { let person: Person init(person: consuming Person) { self.person = person } } let person = Person() let developer = Developer(person: person) person.printInfo()
-
23:43 - Untyped throws
enum IntegerParseError: Error { case nonDigitCharacter(String, index: String.Index) } func parse(string: String) throws -> Int { for index in string.indices { // ... throw IntegerParseError.nonDigitCharacter(string, index: index) } } do { let value = try parse(string: "1+234") } catch let error as IntegerParseError { // ... } catch { // error is 'any Error' }
-
24:19 - Typed throws
enum IntegerParseError: Error { case nonDigitCharacter(String, index: String.Index) } func parse(string: String) throws(IntegerParseError) -> Int { for index in string.indices { // ... throw IntegerParseError.nonDigitCharacter(string, index: index) } } do { let value = try parse(string: "1+234") } catch { // error is 'IntegerParseError' }
-
24:39 - Typed throws - any and Never error types
func parse(string: String) throws -> Int { //... } func parse(string: String) throws(any Error) -> Int { //... } func parse(string: String) -> Int { //... } func parse(string: String) throws(Never) -> Int { //... }
-
28:02 - Passing a NonSendable reference across actor isolation boundaries
class Client { init(name: String, balance: Double) {} } actor ClientStore { static let shared = ClientStore() private var clients: [Client] = [] func addClient(_ client: Client) { clients.append(client) } } @MainActor func openAccount(name: String, balance: Double) async { let client = Client(name: name, balance: balance) await ClientStore.shared.addClient(client) }
-
28:52 - Atomic
import Dispatch import Synchronization let counter = Atomic<Int>(0) DispatchQueue.concurrentPerform(iterations: 10) { _ in for _ in 0 ..< 1_000_000 { counter.wrappingAdd(1, ordering: .relaxed) } } print(counter.load(ordering: .relaxed))
-
29:21 - Mutex
import Synchronization final class LockingResourceManager: Sendable { let cache = Mutex<[String: Resource]>([:]) func save(_ resource: Resource, as key: String) { cache.withLock { $0[key] = resource } } }
-
-
正在查找特定内容?在上方输入一个主题,就能直接跳转到相应的精彩内容。
提交你查询的内容时出现错误。请检查互联网连接,然后再试一次。