大多数浏览器和
Developer App 均支持流媒体播放。
-
Swift 中的新增功能
加入我们,了解 Swift 的最新动态。发现最新语言改进如何让您的代码更容易阅读和编写。探索作为 Swift 包提供且数量越来越多的 API。同时,我们还将向您介绍 Swift 的 async/await 语法、结构化并发功能和参与者。
资源
- Diversity in Swift
- DocC
- Package Collections
- Swift Algorithms on GitHub
- Swift Argument Parser on GitHub
- Swift AWS Lambda Runtime on GitHub
- Swift Collections on GitHub
- Swift Compiler Driver on GitHub
- Swift Evolution
- Swift Forums
- Swift Mentorship Program
- Swift Numerics on GitHub
- Swift Package Index
- Swift System on GitHub
- The Swift Programming Language: Concurrency
相关视频
WWDC21
- 使用 DocC 构建交互教程
- 使用精选集探索和管理 Swift 软件包
- 使用结果生成器在 Swift 中写入 DSL
- 利用 Swift Actor 保护可变状态
- 托管和自动化 DocC 文档
- 探索 Swift 中的结构化并发
- 提升 Xcode 中 DocC 文档的质量
- 认识 Swift 中的 async/await
- 认识 Swift 算法和字体集软件包
- 认识 Xcode 中的 DocC 文档
- Swift 并发功能:幕后故事
- SwiftUI 中的新功能
WWDC20
-
下载
♪ ♪ 嗨! 我是妮可 欢迎来到“Swift的新特性” Swift 5.5是我们有史以来最棒的更新 Swift语言持续以高速进化中 增加许多新功能 包括Swift并发 异步和并发程序设计的全新模型 为了在Swift并发程序设计而生 方便、有效率又安全 此外 我们让在Swift开发 比从前都还轻松 多亏新版的 套件体验 新标准函式库套件 和提升开发者体验的功能
虽然这些功能进化很重要 Swift项目的核心并不在代码 而是社群里的人们 一同协作达成Swift项目的目标 这是为什么我们投入软件同时 也投入在我们的社群是很重要的 我想从Swift的社群倡议 开始说起 多元是Swift社群的核心价值 研究显示 多元的开源项目 更有生产力且决策更佳 接纳各种背景、有多元观点的人 帮助社群蓬勃发展 我们 和其他Swift社群里的成员 看见鼓励活跃参与的机会 在Swift生态圈 和来历更广的开发者 在Swift倡议的多元篇章 Swift多元的任务在于促进 Swift社群的包容性 通过推动更多种声音加入 并让开发者能更容易开始学习 或在Swift贡献 不论他们背景为何 本着倡议的一部分 我们拓展了swift.org博客 来囊括认可和提倡社群中 来自各种背景开发者贡献的文章 我们也在Swift论坛 建立了社群群组 让开发者 能与有类似经验 会遇到同样障碍的开发者交流 想参与在Swift多元 或了解更多 请到swift.org/diversity 我们也想帮助已经在社群的开发者 成长并用Swift达成他们的目标 为了让在提升Swift开源项目的贡献 更加容易 我们最近发布了 Swift导师计划来帮助新人 向其他贡献者寻找方向支持及引导 这个计划不限于Apple项目 也包含整个Swift套件生态圈 和开源工具 再来 我想聊聊套件 套件是打造软件的 重要基石 让你 便利得使用开源代码中 不断成长的数组 Swift社群的成员 想出一些很棒的方案 来帮助开发者寻找套件 像是Swift套件索引 Swift套件索引是个网页 由社群建立 帮助你寻找 支持Swift套件管理员的套件 现在 在Swift 5.5和Xcode 13 我们提供 新方法让你寻找并取得套件 套过提供Xcode工具支持整合 让使用套件在你的项目中 作为你的开发工作流程的一环 能更快速更简单
今年 我们带来Swift套件集合 收录你能使用的Swift套件清单 来自命令行界面和Xcode 13 有了套件集合 你再也不用 在网络上寻找套件 或用网址复制贴上来新增 你仅需浏览一个集合 再从Xcode的 新套件搜寻窗口新增套件 套件集合是简易的JSON文件 在哪都能发布 套件集合是为了让每个人都能 为了不同使用情境 建立套件列表 譬如说 计算机科学课程的讲师 可以整理一系列套件 来教导课堂中的概念 或有些人可以为特定专业或任务 整理套件集合 或为他们的组织整理专用的集合 我们很期待看到大家 用不同方式运用集合 我们有个很棒的简报关于套件集合 我建议你们看看了解详情 套件集合包括 在Xcode的一些强大工具支持 你现在只差导入这步骤就能用 你喜爱的API 当你尝试导入一个找不到的模块时 Xcode会检查是否有套件 在套件集合是你已经配置的 提供该套件 让你能 自动开始使用该套件 一旦你选择使用该套件 所有配置将按照套件集合里的信息 为你自动设定 套件集合也能用搜寻方式查找 能轻松找到适合你的使用情境的套件 如果你今天有兴趣试试套件集合 已经也部分可以使用 包括Apple在GitHub发布的 Swift套件里的套件集合 Xcode安装时就附有Apple集合
如果你有兴趣了解更多 关于套件集合 包括已经在社群中 可使用的集合 查看在swift.org 关于套件集合的新文章 说到你最爱的API,Apple发布 开源Swift套件日益增加的API家族 除了你最爱的套件的 重大优化 今年 我们还发布了四个新套件 首先 我想向你说明Swift集合
Swift集合是全新的数据架构 开源套件 用来辅助 既有Swift标准函式库 Swift套件的初始版本 包含三个最常被请求的 数据架构的应用 Deque,OrderedSet和OrderedDictionary
Deque就像数组 唯一不同在它支持 两端的高效输入与移除 OrderedSet是强大的数组 和集的混合体 如同数组OrderedSet让它的元素依序 并支持随机取用 如同集 OrderSet确保每个元素 只出现一次 并提供高效的会员测试
最后是OrderedDictionary 它是 当顺序很重要时 或我们需要随机取用元素时 接着 我们来聊聊Swift算法 Swift算法是全新的 序列和集合算法开源套件
我们已经在Swift算法新增超过 40种算法 像是产生元素集合的全部组合或排列 或在两个、三个或群组中 由谓词决定的 元素序列迭代 或在集合中选择最小的五个元素 最大的五个 会随机选择五个
要学会字词需要些时间 一旦你学会了 你会很惊讶地发现 有多少算法藏在其中
想要了解更多 我们有个会话 说明全新Swift算法 和集合套件如何让你的代码 更干净 更快速且更正确 现在 我们来聊聊Swift系统 去年秋天 我们让Swift系统开源化 提供通顺的 低阶界面来系统呼叫的函式库 系统在Apple平台,Linux 甚至Windows都通用 我们最近为系统新增了强大的 档案路径类型新API 供调整一般路径作业使用 这些包含了询问或设定扩充 新增及移除组件 和执行路径常态化的功能 路径可以被分解为自身的根 和它相关的组件 档案路径的组件检视是 结构化路径组件的 集合 意思是说它本身就能支持 多个Swift的一般算法
当目标为Windows时 Windows路径 和它复杂的根组件 能被这些新档案路径API全面支持 接着 我们来说明Swift Numerics Swift Numerics今年也有多个 重大更新 去年我们为iOS、tvOS和watchOS 带来Float16 今年 我们让Float16能支持 Apple Silicon Macs 以及产生Float16基础的 复杂数字的功能 另个今年的更新是复杂数字 能支持全部基本函数 像是日志、sine和cosine 因为这些执行是用Swift写成 它们时常比传统的C函式库 更有效率 且能优化 这是原本办不到的 最后 我们来聊聊 Swift ArgumentParser 我们今年持续完善 Swift ArgumentParser 加强像是能产生 给Fish shell用的自动完成脚本 加入短选项 并改善错误信息 我们也跨越了一个重要里程碑 ArgumentParser在今年春天 在Xcode 12.5 可以被Swift套件管理员套用 没错! 如果你近期用过 Swift套件管理员的命令行界面工具 你就已使用过Swift ArgumentParser 接着 我想聊聊我们为Swift 在服务器开发支持做的改变 去年 我们新增支持数个平台 包括Amazon Linux 今年 我们延续先前的工程 通过投入Swift服务器应用的效能 与功能性
我们开始让Linux静态连接能使用 这改善了应用的启动时间 也简化服务器应用的 布署 因此现在能以单一档案进行布署 此外 在Swift 5.5,JSON在Linux 使用的编码与解码 已彻底重新套用 进而为大部分使用情境提升效能 最后 我们加强并优化了 AWS Lambda 执行期函式库本身的效能 这些改善让在AWS Lambda 运行的Swift程序 开启速度快了33% 经由AWS API网关的lambda 调动时间也快了40% 除了优化 AWS执行期函式库效能 我们重构让它能用全新的 async/await模型 而不是闭包 优化Swift开发者经验 是另一个Swift 5.5的关键重点 我想从开发文件开始谈起 杰出的开发文件为架构使用者 创造顺利且能够享受的体验 今年 我们带来DocC 一个文件编译器深度整合 在Xcode 13内 帮助你教导开发者 如何使用你的Swift架构或套件 现在撰写和分享杰出的文件 比从前都还简单
DocC从零开始打造 使用你们已经熟悉且喜爱的 工具和技术 像是你的Swift原始码的 markdown评论 如此你就能轻松撰写开发文件 并做差异比对
我们有四个精彩的会话展示你 DocC开发文件在Xcode的每个层面 我非常建议你们去看看 而现在 我非常开心地宣布 Swift DocC将会在今年开源 开源Swift DocC能让开发者 更轻松地产生很好的开发文件 在所有支持Swift的平台
在Swift 5.5 我们投入在类型检查器的 质量与效能优化 这个优化带来一个结果 是你将会在编译你的代码时 看到更少 “expression too complex”错误 我们也加速了 数组常值的类型检查效能
在这次发布 我们也加强了 开发者生产力 带来三个重大改善来加速增量建置 首先 我们现在支持增量导入 也就是我们不再需要重建置 每个导入模块资源文件 在模块改变时 此外 我们现在还提前运算 模块相依性图 如此我们能快速开始增量建置 并只在有改变的地方 最后 我们扩展了选择性重新编译 来跟扩充功能互动 也就是更少 重新编译 在你更改扩充功能的本体时 以SwiftDriver开启开源专案为例 平均而言 有了Swift 5.5的 增量导入 我们现在导入模块改变时 少重编译十分之一的档案 而且建置时间也大约减少了三分之一 增量导入的效能改善 代表你可以模块化你的项目 并改变导入的模块 建置效能又不会受损 顺带一提 一些效能改善 是因为Swift项目的重大里程碑 才能实现 首个部分由Swift写成的编译器 这是Swift Driver 整合Swift 原始码的编译程序设计 这个项目从2019年末开始 如今的Xcode 13 已经是Swift编译的预设 最后 我们来谈谈一些 让Swift内存管理更有效率的改善 让Swift程序设计内存重取得更快 Swift类别实例使用 自动引用技数 ARC 来追踪一个特定对象 在任何时间下有多少个引用 多数情况下 这代表内存管理 在Swift肯定没问题 而你不需要 自己去担心内存管理 ARC自动空出 被类别实例用掉的内存 在不再需要那些实例时 要能如此 每当新的引用被创建 Swift编译器写入保留作业 每当停止使用新引用时 写入发布作业 今年 我们带来新方法 追踪编译器里的引用 大幅减少编译器 执行保留和发布作业的数量 我们已看见可量测的效能 和代码大小改善 我们新增一个Xcode设定 优化对象生命期 让你能看到这个全新 效用极强的ARC优化效果在 你的代码中 更多关于ARC的信息 请看“Swift内的ARC”会话
这是Swift 5.5 带给你的一些改善 接着 提姆将跟你们聊聊Swift并发 以及其他在Swift语言的进化 谢谢你 妮可 我们都对Swift并发感到非常兴奋 但在我说到那之前 我想讨论 一些我们的Swift做的其他改变 让日常程序设计简化并改善
这里是一个我们今年做的 人类工程优化的列表 SE数字代表Swift进化提议 这里每个提议都是由社群里的成员 撰写 在Swift进化论坛被讨论 并由Swift核心团队核可 在正式被接纳进入这个语言之前 所有SE提议 不论被接受或拒绝 或仍在讨论中 可以在Github的 Swift进化仓库找到 我们来看看其中几个改变 首先 结果建置器 在SwiftUI刚发表时 推出了新语句 可以用来 快速且轻松地描述复杂对象阶层 过去这一年 这个语句 已通过Swift进化过程 标准化且改良 让它能 更简易得使用在多种广泛的框架 如果你想使用这个强大的技术 我们有一个会话专门投入在 如何使用结果建置器 Codable协定 是一个方便的方法来连载你的数据 但它长期被明显地忽略 用这个双案件列举来看 为了让它相容于Codable 你先前必须 手动执行这整个文件样板 现在 你只需要宣告Codable兼容 编译器就会帮你完成这些工作
我们也完成了一些重大改善 在Swift类型检查器 如你所知 在Swift的类型推论 代表你可以忽略多余的类型信息 这里 它让你缩短Coffee.regular 成只有.regular 像是列举的架构也能用别种方式呈现 譬如 你可能有类型集合 用来让协议兼容 并想用你的API中 那些类型的实例 你现在可以参照这些类型实例 用你用在列举的相同点记法 通过宣告一些你的协议中的静态属性 这是Swift类型检查器优化 带来的改变 这让它能更广泛地解开 一般框架中的静态属性 包括连锁属性索引 像是这里的.large 这让函式库作者能用自然、易用 且与列举相似的API 来建置复杂的通用数据模型
属性包装器在今年也有改进
属性包装器是应用常见语义 到属性上的方便工具 你们多数人可能有自己的属性包装器 在结构上使用@propertyWrapper注解 这是一个新增属性非空白的 需求的范例 代入使用SE-0293 这些相同的属性包装器就能被用在 函式和闭包参数
累积起来的这些和其他语言上的更改 能简化很多一般编码问题 我们在一个简单的 SwiftUI范例代码框架中 一起检视它们 这是个有单一属性的SwiftUI检视 持有数组设定 和呈现其他设定的 清单主体 每个旁边带有Toggle 我们回顾这段代码 看看 全新Swift 5.5功能如何简化它 首先 Toggle初始化很显然重复了 这样的重复在之前是必要的 但我们已经放松使用#if的规则 让它能包围后缀表示法 像是这里的 toggleStyle更改器 这让我们 能分解出多余处 SwiftUI也已经更新到能使用 我刚刚说过的类型检查器的新优化 因此你可以使用自然点记法 在许多地方 要…要为设定数组 定义索引有点别扭 接着还要将数组编入闭包内 我们宁可直接采用这些值 现在你可以跳过被呈现绑定 直接进入列表构造器 这能接着改变数组的值 为属性包装器新支持的自变量 让我们用金钱符号写闭包自变量 让我们在闭包中能有界限设置 这反过来让我们取得 被包装值和绑定 最后 Swift编译器现在透明地转换 在CGFloat和Double之间 让你排除许多多余的数字转换 在跟Apple平台API互动时 如你所见 我们持续 精进核心语言的努力 让你每天写的代码 比从前都简单 并创造更多 让函式库作者建置丰富 且易用的API的机会 更多关于SwiftUI今年 带来的多个程序设计改变的信息 请看“SwiftUI有什么不同”会话 当然 Swift 5.5的重头戏 是一系列连锁功能 来支持异步和并发程序设计 我稍后就会介绍到 但首先 让我简短说明所谓“异步” 和“并发”的意思 软件项目是由多个结构块代码 按某种顺序执行组成 在最简单的案例中 这些结构块 按照简单顺序一个接一个执行 但其他架构也很常见 像是网络API常被设计成 异步的方式 在这些API中 你送出一个请求 到远程服务器后 可能有很长的延迟 直到你收到响应 需要做更多动作 理想上 你的代码会在这段延迟期 延缓执行 才不会用掉任何资源 在你能针对响应有所作为之前 相反地 并发代码是当 你有两个或更多结构块代码 你希望同时执行 这些通常是独立但相关的作业 处理一支影片的多个架构 以此为例 或同时执行下个 ML分类器的迭代 你用先前得到的结果 来更新UI 了解这些概念后 我们来看看简单的异步程序设计范例 先不用Swift的新功能 如果你有不少iOS、MacOS 程序设计经验 你可能写过很多与此相似的代码 这使用URLSession类别的基础 来呼叫网络 dataTask方法是异步作业 你要用闭包自变量呼叫 在得到结果时 你的闭包被该结果呼叫作业 然而 这样用闭包来表达异步代码 会让作业顺序有些笨拙 你扫过这些代码就能看出来 首先,有些初始设定 以及dataTask方法会回传 任务控制代码 接着我们延续任务控制代码 来启动背景作业 fetchImage函式实际上 在这时才会回传 任何呼叫我们的人一定要准备好继续 就算我们实际上还没完成 我们被请求的工作 再来 在网络运算结束后 这个闭包会有机会处理结果 希望一切进行得顺利 我们就能 用最终结果呼叫完成控制代码 除了执行顺序有些别扭 使用完成控制代码也让我们无法 使用try/catch异常处理 留意到dataTask是如何 在完成控制代码 提供额外错误参数 和我们如何 用每个可能的错误唤起完成控制代码 要了解Swift 5.5对此如何改善 我们来看看代码的这一行 注意到这个呼叫回传一个任务 和代表背景作业的 抽象控制代码 这其实不是我们要的 我们只需要拿到数据 但我们先不管这个 先看看结果如何 因为我们是跟HTTP互动 我们还需要撷取一些回复元数据 所以这个函式需要回传一对 包含第一个 真实数据 和第二 额外信息 通过结构化这个函数调用 它回传这些数据 我们现在能用 try/catch异常处理来消除 许多先前范例中的样板 我们只需要一小部分的语句 来告诉编译器 我们的函式可以延迟 一旦数据方法开始 而我们在作业完成前 就没办法完成任务 这正是新的await关键词的用途 我们来用上下文来看看 这是我们的fetchImage函式 现在长的样子 你可以看到 这个代码现在 更容易遵循 控制从上到下遵循 我们不再需要套用闭包 我们也能用try/catch异常处理 await关键词指出 fetchImage函式可以被延迟的时间点 搁置先不执行 直到允许它继续的事件发生
在这个案例中 一旦URLSession 发动请求 我们的函式就会被Swift执行期延滞 同时在其他地方继续作业 最终结果预备好后 不论响应是成功或出现错误 只有那时我们的函式才会继续 如果回应是成功 我们会完成 数据和响应变量的初始化 如果是个抛出错误 我们会传回给呼叫我们的人 异步函式被延迟时 不会用掉任何资源 也就是说 它没有占用到线程 这让Swift执行期重复利用这个函式 为其他工作执行的线程 这会让很少的线程 在多个异步作业中共享
语句上 async和await关键词 以类似方法来抛和试 async改变函式的宣告为 这个函式必须编译为能够支持延缓 使用await关键词标示任何呼叫 async函式、方法或闭包 当然 完整的机制比我展示的 有趣多了 你可以观看 “在Swift与async/await相遇” 还有“Swift并发:幕后作业” 学习这些如何运作 再来 我们来看看Swift的新并发支持 这建立于我刚说明的 async/await基础上
这是一个渲染并整合 三张不同图片的函式 这里写到 这些作业是有次序的 背景、前景和首图 会一个接一个被渲染 一个开始 是接在前一个结束后 我们希望渲染作业平行进行 但只执行这些在不同线程 是不够的 我们也需要合并作业 保留直到我们拿到三个结果 这在某方面上 与我刚提到的异步编码相似 我们标记这个函式为“async” 这样在它需要等待时 可以暂停 等其他线程的结果被运算出来 接着 我们用async的let命令语句 平行执行头两个作业 async的let命令看起来很像 变量初始化 而它基本上就是这样 但这个初始化会跟其他代码 平行执行 直到你尝试使用结果 因为背景和前景变量 在下async的let命令时被初始化 必要的话 Swift的执行 会暂停合并作业直到那些值预备好 我们用await关键词来标记合并函式 以标明这个 这段代码最重要的部分是 背景作业不能存活得比这个函式还久 也就是说 这个函式不能 也不会回传 假如两个背景作业 有任一个还在执行 如果有个错误在这个函式的任何地方 抛出 Swift执行期 会持续等待背景任务完成 这里 我强调出一个try标记 指出 首图的运算可能会抛出 但这个情形适用于所有全部抛出错误 就算在分别线程发生 为了保持有抛出错误时的回应度 Swift执行期会示意 未完成任务让它们有机会提早完成 我们关于结构化并发的会话 提供更多细节 包括这个取消机制 和其他我所提的async的let命令语句 弹性替代方法的讨论 在上一段 我展示了Swift 5.5 如何在多线程中执行作业得更轻松 以有秩序 结构化的方式 当然 这样不太够 每当两个分别的线程共享资料 你便冒着资料会不一致 甚至是损坏的风险 Swift的新演员构造器 帮助你保护你的数据 不遇到这些问题 同样的 我们用你可能自己写好的 范例代码开始 这是搜集数据的类别 它包含了一个计数 和很多其他代码 会呼叫增量方法来更新该计数 每当有趣的事情发生时 不幸地 这段代码在多线程系统 不太好用 如果两个或更多线程同时呼叫 增量方法 你可能造成严重损坏的计数 把这个类别改变成Swift演员 能保护损坏 演员会延迟任何能造成 数据损坏 直到能安全那个特定更动时 这代表你通常需要用await 在你从演员方法外呼叫演员时 演员也能完美无缺地 跟async/await互动 注记这个像async的发布方法 让它延迟 在等待网络作业的同时 在它被延迟同时 其他方法可以执行 在这个演员身上 不必等待网络作业 来完成 也不用冒着数据损坏的风险 演员是引用类型 就像类别 但它们遵从一系列规定 设计来确保 演员安全使用多线程环境 把你的资料封包成演员 你就清楚陈述说你期望这些数据 要并发取用 以及你想要Swift编译器和执行期 同步取用 确保没有损坏的可能性 当然 我们有完整会话 专门致力于Swift的新演员构造器 在那 你能找到如何利用 它所提供全部可能性 在我们收尾前 我们稍微聊聊 Swift的未来 我们坚信三个在Swift 5.5 带来的关键概念 异步函式 架构化并发性 及演员 是很好的基石 为了创造安全 又高效能的代码 在Swift 6 我们研究了几个方法 让编译器抓取更多种类的并发性错误 在早期开发阶段 提供你更多细节的错误 以及修复这些问题的指引 我们的目标很简单 是要彻底消灭 最常见的并发程序漏洞 为了让异步与并发程序设计 不要比其他类型程序设计还复杂 以及 当然 在我们持续改善 编译器对这些概念的诠释时 我们也预期代码使用新架构 能变得比现况更有效率
Swift是个开放的协作成果 我们欢迎你的投入 一起让Swift 6更上层楼 告诉我们你使用Swift 5.5的体验 这些新功能对你来说有多好用 以真实世界的应用程序开发而言? 试试其中一个编译器截图 你可以在swift.org上找到 我们提供这些截图 让你能将它们 安装进Xcode 并在我们开发途中尝试出新功能 通过使用这些截图 你能协助引导下个版本的Swift Swift论坛是 专案的命脉 每个我提到的功能 展开了生命 通过在Swift进化论坛提案 那里 多元背景的一群人协助提炼它 成为一个工作提议 我们也有多个论坛投入在 很多Swift的其他面向 包括为新用户打造的协助专区 来与Swift社群交换兴趣新闻 还有很多方法能让Swift变得更好 我们期待邀请更多人参与 像是通过妮可在这个会话最一开始 提到的全新导师计划 唯一的要求是真诚渴望 在社群中 为每个人帮助Swift进步 我很期待听到你们的消息 也希望你享受这场会谈 [音乐]
-
-
6:16 - Deque
import Collections var colors: Deque = ["red", "yellow", "blue"] colors.prepend("green") colors.append("orange") // `colors` is now ["green", "red", "yellow", "blue", “orange"] colors.popFirst() // "green" colors.popLast() // "orange" // `colors` is back to ["red", "yellow", "blue"]
-
6:25 - Ordered set
import Collections var buildingMaterials: OrderedSet = ["straw", "sticks", "bricks"] for i in 0 ..< buildingMaterials.count { print("Little piggie #\(i) built a house of \(buildingMaterials[i])") } // Little piggie #0 built a house of straw // Little piggie #1 built a house of sticks // Little piggie #2 built a house of bricks buildingMaterials.append("straw") // (inserted: false, index: 0)
-
6:42 - Ordered dictionary
import Collections var responses: OrderedDictionary = [200: "OK", 403: "Forbidden", 404: "Not Found"] for (code, phrase) in responses { print("\(code) (\(phrase))") } // 200 (OK) // 403 (Forbidden) // 404 (Not Found)
-
7:39 - Swift Algorithms
import Algorithms let testAccounts = [ ... ] for testGroup in testAccounts.uniquePermutations(ofCount: 0...) { try validate(testGroup) } let randomGroup = testAccounts.randomSample(count: 5)
-
7:52 - Swift System
import System let fd: FileDescriptor = try .open( "/tmp/a.txt", .writeOnly, options: [.create, .truncate], permissions: .ownerReadWrite) try fd.closeAfter { try fd.writeAll("Hello, WWDC!\n".utf8) }
-
8:06 - FilePath manipulation APIs
import System var path: FilePath = "/tmp/WWDC2021.txt" print(path.lastComponent) // "WWDC2021.txt" print(path.extension) // "txt" path.extension = "pdf" // path == "/tmp/WWDC2021.pdf" path.extension = nil // path == "/tmp/WWDC2021" print(path.extension) // nil path.push("../foo/bar/./") // path == "/tmp/wwdc2021/../foo/bar/." path.lexicallyNormalize() // path == "/tmp/foo/bar" print(path.ends(with: "foo/bar")) // true!
-
9:01 - Float16 support on Apple silicon Macs
import Numerics let x: Float16 = 1.5 let y = Float16.exp(x)
-
9:05 - Complex elementary functions
import Numerics let z = Complex(0, Float16.pi) // πi let w = Complex.exp(z) // exp(πi) ≅ -1
-
11:07 - AWS Lambda runtime now with async/await
import AWSLambdaRuntime import AWSLambdaEvents @main struct HelloWorld: LambdaHandler { typealias In = APIGatewayV2Request typealias Out = APIGatewayV2Response func handle(event: In, context: Lambda.Context) async throws -> Out { .init(statusCode: .ok, body: "Hello World") } }
-
14:52 - Memory management
class Traveler { var destination: String } func test() { let traveler1 = Traveler(destination: "Unknown") // retain let traveler2 = traveler1 // release traveler2.destination = "Big Sur" // release print("Done traveling") }
-
17:04 - Codable synthesis for enums with associated values: A two-case enum
enum Command { case load(key: String) case store(key: String, value: Int) }
-
17:11 - Codable synthesis for enums with associated values: Before
// You used to have to manually implement all of this boilerplate. enum Command: Codable { case load(key: String) case store(key: String, value: Int) init(from decoder: Decoder) throws { let container = try decoder.container(keyedBy: CodingKeys.self) if container.allKeys.count != 1 { let context = DecodingError.Context( codingPath: container.codingPath, debugDescription: "Invalid number of keys found, expected one.") throw DecodingError.typeMismatch(Command.self, context) } switch container.allKeys.first.unsafelyUnwrapped { case .load: let nested = try container.nestedContainer( keyedBy: LoadCodingKeys.self, forKey: .load) self = .load( key: try nested.decode(String.self, forKey: .key)) case .store: let nested = try container.nestedContainer( keyedBy: StoreCodingKeys.self, forKey: .store) self = .store( key: try nested.decode(String.self, forKey: .key), value: try nested.decode(Int.self, forKey: .value)) } } func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) switch self { case let .load(key): var nested = container.nestedContainer(keyedBy: LoadCodingKeys.self, forKey: .load) try nested.encode(key, forKey: .key) case let .store(key, value): var nested = container.nestedContainer(keyedBy: StoreCodingKeys.self, forKey: .store) try nested.encode(key, forKey: .key) try nested.encode(value, forKey: .value) } } /// Contains keys for all cases of the enum. enum CodingKeys: CodingKey { case load case store } /// Contains keys for all associated values of `case load`. enum LoadCodingKeys: CodingKey { case key } /// Contains keys for all associated values of `case store`. enum StoreCodingKeys: CodingKey { case key case value } }
-
17:15 - Codable synthesis for enums with associated values: After
enum Command: Codable { case load(key: String) case store(key: String, value: Int) }
-
17:26 - Static member lookup
enum Coffee { case regular case decaf } func brew(_ coffee: Coffee) { ... } brew(.regular)
-
17:49 - Flexible static member lookup
protocol Coffee { ... } struct RegularCoffee: Coffee { } struct Cappuccino: Coffee { } extension Coffee where Self == Cappucino { static var cappucino: Cappucino { Cappucino() } } func brew<CoffeeType: Coffee>(_ coffee: CoffeeType) { ... } brew(.cappucino.large)
-
18:25 - Property wrappers on parameters
@propertyWrapper struct NonEmpty<Value: Collection> { init(wrappedValue: Value) { precondition(!wrappedValue.isEmpty) self.wrappedValue = wrappedValue } var wrappedValue: Value { willSet { precondition(!newValue.isEmpty) } } } func logIn(@NonEmpty _ username: String) { print("Logging in: \(username)") }
-
19:02 - Ergonomic improvements in SwiftUI code: Before
// Instead of writing this... import SwiftUI struct SettingsView: View { @State var settings: [Setting] private let padding = 10.0 var body: some View { List(0 ..< settings.count) { index in #if os(macOS) Toggle(settings[index].displayName, isOn: $settings[index].isOn) .toggleStyle(CheckboxToggleStyle()) #else Toggle(settings[index].displayName, isOn: $settings[index].isOn) .toggleStyle(SwitchToggleStyle()) #endif } .padding(CGFloat(padding)) } }
-
19:37 - Ergonomic improvements in SwiftUI code: After
// You can now write this. import SwiftUI struct SettingsView: View { @State var settings: [Setting] private let padding = 10.0 var body: some View { List($settings) { $setting in Toggle(setting.displayName, isOn: $setting.isOn) #if os(macOS) .toggleStyle(.checkbox) #else .toggleStyle(.switch) #endif } .padding(padding) } }
-
22:20 - Asynchronous programming with async/await: Before
// Instead of writing this... func fetchImage(id: String, completion: (UIImage?, Error?) -> Void) { let request = self.imageURLRequest(for: id) let task = URLSession.shared.dataTask(with: request) { data, urlResponse, error in if let error = error { completion(nil, error) } else if let httpResponse = urlResponse as? HTTPURLResponse, httpResponse.statusCode != 200 { completion(nil, MyTransferError()) } else if let data = data, let image = UIImage(data: data) { completion(image, nil) } else { completion(nil, MyOtherError()) } } task.resume() }
-
23:58 - Asynchronous programming with async/await: URLSession.shared.data(for:)
let (data, response) = try await URLSession.shared.data(for: request)
-
24:40 - Asynchronous programming with async/await: After
// You can now write this. func fetchImage(id: String) async throws -> UIImage { let request = self.imageURLRequest(for: id) let (data, response) = try await URLSession.shared.data(for: request) if let httpResponse = response as? HTTPURLResponse, httpResponse.statusCode != 200 { throw TransferFailure() } guard let image = UIImage(data: data) else { throw ImageDecodingFailure() } return image }
-
27:06 - Structured concurrency
func titleImage() async throws -> Image { async let background = renderBackground() async let foreground = renderForeground() let title = try renderTitle() return try await merge(background, foreground, title) }
-
29:26 - Actors
actor Statistics { private var counter: Int = 0 func increment() { counter += 1 } func publish() async { await sendResults(counter) } } var statistics = Statistics() await statistics.increment()
-
-
正在查找特定内容?在上方输入一个主题,就能直接跳转到相应的精彩内容。
提交你查询的内容时出现错误。请检查互联网连接,然后再试一次。