本期是 Swift 编辑组自主整理周报的第六十三期,每个模块已初步成型。各位读者如果有好的提议,欢迎在文末留言。
Swift 周报在 GitHub 开源,欢迎提交 issue,投稿或推荐内容。目前计划每两周周一发布,欢迎志同道合的朋友一起加入周报整理。
锻炼使你突破极限,休息让你完成蜕变,变强就是突破加上蜕变。Swift社区期待与你一起共为强者!👊👊👊
周报精选
新闻和社区:“美国本土外‘覆盖范围最广’”,苹果公司深圳实验室启用提案:Nonescapable类型提案正在审查。
Swift 论坛:提议讨论字符串编码名称
推荐博文:Swift6 的发布
话题讨论: 你认为今年会有牛市吗?
上期话题结果
根据投票结果,小编认为品牌之间的竞争给了企业足够的压力和动力去创造更好的产品,这最终有利于消费者。
2024 年 10 月 12 日
参考消息网 10 月 12 日报道据香港《南华早报》网站 10 月 11 日报道,苹果公司在中国南方科技中心深圳设立的一个应用研究实验室日前开始启用。在与华为公司等中国国内企业竞争加剧的情况下,这家美国巨头加大了对全球最大智能手机市场中国的投入。
据报道,该设施于 10 日在河套深圳园区开始运营。河套深圳园区是根据中央政府指示开发的合作区,旨在深化深圳与香港的科技合作伙伴关系。
今年 3 月,苹果公司宣布计划在深圳建立一个新的实验室。该公司表示,这将增强对苹果主要产品的测试和研究能力,同时也有助于加强该公司与当地供应商的合作。
这一实验室首期项目占地 2 万平方米,将成为苹果公司在粤港澳大湾区的研发中心。
据上述报道,该实验室最终将发展超过 1000 人的中外高端人才研发团队,并成为苹果公司在美国本土外“覆盖范围最广”的实验室。
苹果公司 3 月表示,已在北京、上海、苏州和深圳设立了研究中心。该公司称,过去5年,其在中国的研发团队规模实现翻倍增长。
苹果公司在中国智能手机市场面临日益激烈的竞争,总部位于深圳的华为公司在中国的手机业务已经复苏。华商光电科技产业研究院 9 日发布的一份报告显示,今年 8 月,华为公司在中国内地的智能手机销量近 4 年来首次超过苹果公司。
2024 年 10 月 12 日
美国国家劳工关系委员会周五表示,苹果被美国劳工委员会指控,通过限制员工使用社交媒体和工作场所消息应用程序 Slack,干涉了员工集体倡导改善工作条件的权利。这是美国劳工委员会本月第二次对苹果提出投诉。上周,该机构指控苹果公司要求全国员工签署非法的保密、不披露和竞业禁止协议,并实施过于宽泛的不当行为和社交媒体政策。(来源:金融界)
2024 年 10 月 10 日
10 月 10 日消息,本周早些时候,曾有外媒在报道中提到,苹果公司全球采购与供应管理副总裁 Dan Rosckes,即将退休,结束 24 年的苹果生涯。
而从外媒最新的报道来看,苹果 Vision Pro 团队的领导者丹•里奇奥(Dan Riccio),也即将退休。
同 Dan Rosckes 一样,即将退休的丹•里奇奥的工作,也将由苹果其他的高管接手,Mike Rockwell 将接管 Vision Pro 团队的日常运营,由硬件工程高级副总裁约翰•特努斯监督。
即将退休的丹•里奇奥是在 1998 年加入苹果的,与现任 CEO 库克同一年开始在苹果的工作,至今已有 26 年。有外媒在报道中提到,在苹果工作已 26 年的丹•里奇奥,在乔布斯时期和库克时期都是重要高管。
在 1998 年进入苹果时,丹•里奇奥是在产品设计团队工作,进入苹果的第 12 年,也就是 2010 年,他升任 iPad 硬件工程副总裁,两年之后晋升为高级副总裁,领导苹果的硬件工程。
在苹果硬件工程高级副总裁的岗位上,丹•里奇奥有 9 年,直到 2021 年的 1 月份苹果宣布他将领导一个新的项目时才卸任,当时的接任者是 2013 年开始担任硬件工程副总裁、晚他 3 年加入苹果的约翰•特努斯,后者是目前的苹果硬件工程高级副总裁,是库克潜在接任者中的热门人选。
在 2021 年卸任硬件工程高级副总裁、负责一个新的神秘项目时,苹果方面并未披露项目的具体消息,但后来的消息表明就是 Vision Pro,他以副总裁的身份领导这一项目团队,直接向 CEO 库克汇报。
值得注意的是,丹•里奇奥将退休的消息,在今年3月份也曾出现过,不过当时外媒在报道中称他是计划退休。
丹•里奇奥即将退休,也就意味着苹果的 Vision Pro 团队,今年有两员大将退休。在今年的 4 月份,有外媒在报道中称 Vision Pro 市场营销主管 Frank Casanova,已经退休。
2024 年 10 月 8 日
我们很高兴在此公布 2025 年 Swift Student Challenge。挑战赛为新一代学生开发者提供了宝贵的机会,让他们可以使用 Swift 构建 App Playground,尽情展现创造力和编程技能。
下一届挑战赛的申请将于 2025 年 2 月开放,持续三周。
我们将选出 350 名 Swift Student Challenge 获奖者,以表彰在创新思维、卓越创意、社会影响或多元包容等方面表现出色的优秀作品。我们还将在这些获奖者中进一步选出 50 名打造了非凡作品的杰出获奖者,他们将受邀亲赴位于库比提诺的 Apple 园区度过振奋人心的三天,期间他们将能从 Apple 专家和工程师那里收获宝贵的见解,与同伴沟通交流,并获得一系列令人难忘的经历。
所有挑战赛获奖者都将获得为期一年的 Apple Developer Program 会员资格,以及 Apple 准备的特别礼物等。
为帮助你做好准备,我们发布了新的编程资源,包括专为学生设计的 Swift Coding Club,以帮助参赛者培养未来职业发展所需的技能、建立社区和为挑战赛做好准备。
SE-0444 成员导入可见性 提案通过审查。该提案已在 第六十二期周报 正在审查的提案模块做了详细介绍。
SE-0445 改进 String.Index 的打印描述 提案通过审查。该提案已在 第六十二期周报 正在审查的提案模块做了详细介绍。
SE-0448 Regex 断言背后的含义 提案通过审查。
提案介绍:Regex 支持向前看断言,但目前不支持向后看断言。我们建议增加这些。
SE-0446 Nonescapable类型 提案正在审查。
我们提议添加一种新的类型约束 ~Escapable
,用于那些可以在本地复制但不能在当前上下文之外进行赋值或转移的类型。这与通过 SE-0390 引入的 ~Copyable
类型相互补充,提供了另一种编译时强制执行的生命周期控制,能够用于实现安全且高效的 API。
此外,这些类型还将支持生命周期依赖约束(将在未来的提案中跟踪),允许它们安全地持有指针,这些指针引用存储在其他类型中的数据。
此功能是拟议的 Span
类型系列的关键要求。
SE-0447 Span: 连续存储的安全访问 提案正在审查。
我们引入 Span<T>
,这是一种与容器无关的访问连续内存的抽象。它将扩展 Swift 代码的表现力,而不会影响我们所依赖的内存安全属性:时间安全性、空间安全性、明确的初始化以及类型安全性。
在 C 系列的编程语言中,内存可以通过指针(理想情况下还包括长度)与任何函数共享。这使得连续内存能够与不了解调用者所使用的容器布局的函数共享。堆分配的数组、连续存储的命名字段,甚至单个栈分配的实例都可以通过 C 指针访问。我们的目标是使 Swift 中能够实现类似的习惯用法,同时不妥协于 Swift 的内存安全性。
该提案建立在不可逃逸类型(~Escapable)之上,并且是编译时生命周期依赖注释(Compile-time Lifetime Dependency Annotations)的前驱,后者将在接下来的几周内提出。BufferView 路线图论坛线程是该提案的前身。该提案还依赖以下提案:
SE-0449 允许 nonisolated 以防止全局行为者推断 提案正在审查。
这个建议允许用 nonisolation
注释一组声明,以防止全局参与者推断。此外,它扩展了关于何时可以在存储属性上写入非隔离性的现有规则,从而提高了可用性。
1) 提议字符串编码名称
内容大概
很高兴看到这个 API 的提案!正如你所提到的,这确实是 String 中一个重要的缺失功能,相较于 CFString,它将非常有用。
决定哪些编码应该可用(例如用于 String(data:encoding:)
)是“未来的方向”。
我不确定是否应该立即添加静态属性。如果可能的话:
FoundationEssentials
将仅为内置编码提供静态属性。FoundationInternationalization
可能会为 ICU 编码提供静态属性,或者这些编码可能仅动态可用?我倾向于赞同这种方法。背景是,CoreFoundation 提供比 Foundation 更多的编码,因为 CoreFoundation 是为旧版 macOS 应用程序实现的,依赖 Carbon 提供的编码转换。Foundation 本身仅支持少量编码,这些编码大致相当于 NSStringEncoding/String.Encoding
常量中定义的编码。我认为,如果 String.Encoding
包含所有这些编码,而 Foundation API 从未支持这些编码,可能会引起混淆。
对于一些常见编码,我们可以考虑将它们降级到 FoundationEssentials
,或者如果我们认为转换足够重要,可以添加新的 String.Encoding
选项(例如,在 Swift 6 中,我们将 isoLatin1 和 macOSRoman 编码转换从 Foundation 降级到 FoundationEssentials,因为这些编码转换常用于URL相关的API)。最终,我希望能实现 @benrimmington
提到的方法,在 FoundationEssentials
中,String.Encoding
仅提供 FoundationEssentials
提供的编码转换,而 FoundationInternationalization
可以添加额外的ICU编码。
@YOCKOW,你认为仅使用当前可用的 String.Encoding API,而不添加新静态属性(因为这就是 Foundation 当前支持的转换)是否有价值?
首先,日本有15%的网站仍然使用 Shift JIS。(UTF-8 占 80%。)
他们真的使用标准的 Shift JIS,还是使用带有微软扩展的 CP932(Windows-31J)版本?你的来源没有提到,但确实指出 Shift JIS 曾被广泛使用是因为 Windows 的普及。
编辑:根据维基百科的回答——“许多用户和软件包(包括微软库)将 Shift JIS 编码声明为 Windows-31J 数据,尽管它包含一些额外字符,而且某些现有字符映射到 Unicode 时有所不同。这导致了WHATWG HTML标准将编码标签 shift_jis 和 windows-31j 视为可互换的,并在其‘Shift_JIS’编码器和解码器中使用了 Windows 变体。”
因此,现有行为更具互操作性,如果新增的API未保留这种行为,可能会导致混淆。
编辑2:根据提供的来源,WHATWG 似乎有一个新的编码标准(https://encoding.spec.whatwg.org/),故意偏离IANA,以解决用户代理之间的互操作性问题。标准的语言表明,它有意取代IANA(包括取消对其注册表的任何依赖,并出于安全原因移除字符集的可扩展性)。Rust 的实现详细说明了具体的区别——
在某些情况下,编码标准指定了常用的未扩展编码名称,而在 IANA 术语中,考虑到编码标准统一到编码中的扩展,另一个标签可能更为精确。
编码 IANA
Big5 Big5-HKSCS
EUC-KR windows-949
Shift_JIS windows-31j
x-mac-cyrillic x-mac-ukrainian
在其他情况下,编码标准统一了编码的未扩展和扩展版本,编码获得了扩展版本的名称。
IANA 统一到编码
ISO-8859-1 windows-1252
ISO-8859-9 windows-1254
TIS-620 windows-874
既然相关的 Web 标准似乎已经超越了 IANA 字符集,特别是 Swift 现有 API 已经与其对齐,我们是否应该实现这一取代标准?
编辑3:该取代标准还有一个优点,即它使用“编码”一词,而非“字符集”——这已经与 Swift 的用法一致。确实,越思考,越觉得 String.Encoding
的行为是故意设计成反映当前编码标准的。
2) 提议进展SE-0446:Nonescapable 类型
内容大概
SE-0446: 非逃逸类型的审查现已开始,将持续到2024年10月1日。
本提案涵盖了对非逃逸类型支持的第一阶段;它涵盖了限制在当前作用域内的非逃逸类型的基本语义。然而,该提案本身不提供超出此范围的生命周期依赖表达机制,这意味着目前没有安全的方法来初始化或返回Escapable类型的值。为了便于对此功能进行实验,上述工具链还提供了对@lifetime属性的一些支持,该属性必须用于表达由初始化器或返回值生成的Escapable值的生命周期依赖。然而,该属性的确切行为不包括在此次审查中,可能会在未来单独审查并接受之前发生变化。
3) 提议进展SE-0447:跨度:安全访问连续存储
内容大概
SE-0447 “Span:安全访问连续存储” 的审查现已开始,将持续到 2024 年 10 月 1 日。
本提案是 SE-0446 “非逃逸类型”的库对照部分,也是首个采用此类型的提案。在这些工具链中,withSpan() 函数可用于数组系列类型(如 Array、ArraySlice、ContiguousArray),以及 UTF8View(如 String.UTF8View
、Substring.UTF8View
)和 UnsafeBufferPointer
系列。如果元素类型是 BitwiseCopyable,则还可以使用 withBytes() 函数,提供一个 RawSpan。虽然这些 with(Raw)Span 操作并未专门提出,但它们提供了一种方法来试用 Span、其 API 以及它作为非逃逸类型如何与Swift代码交互。
4) 讨论Swift 6 是一门好的首选语言吗?
内容大概
Swift 6 是否适合作为第一编程语言?
要求初学者不使用全局变量,这与“简单”和“作为第一编程语言”的理念有些冲突。
虽然一些教材(如《计算机程序的构造与解释》)早期引入了全局变量,但通常是为了说明其弊端,随后转向更好的技术。虽然这本书使用了不少赋值操作,但并不依赖于全局变量。
如今,大多数流行语言都支持词法作用域和闭包,因此在教授其他语言时,也没有必要依赖全局变量。此外,专为儿童设计的编程语言 Smalltalk 完全没有全局变量。
然而,这些教材通常针对大学课程,而这里讨论的是“Swift 6 适合作为第一编程语言吗?”的问题。现今的孩子,可能在上大学之前(甚至 8 到 12 岁时)就接触编程了。相比之下,尽管 Smalltalk 最初是为孩子设计的,但如今很少有人推荐它作为儿童的第一编程语言。
我并不建议一种理想的课程设计,更多的是分享我在培养自己孩子学习编程时的经验。比如,Arduino 编程(青少年常见的 STEM 入口点)经常使用顶层变量(通常用于定义常量或数据)。
对于从零开始学习编程的人来说,单线程编程更容易理解,因此全局变量在初学阶段既不危险又容易掌握。尽管我认为今天的孩子可能有不同的学习愿望和切入点,但我仍会建议家长为 10 至 12 岁的孩子选择 Python,它比 Swift 简单得多,不用担心多线程、数据竞争等复杂概念。
(当然,在专业代码中,全局变量是不好的,但我们这里讨论的是初学者学习编程的第一步——“第一编程语言”)
总的来说,我认为 Swift 不应该在初学者学习过程中因为并发问题对他们发出警告,除非他们确实在编写涉及并发的代码。
5) 讨论有没有办法在不使用 SWIFT_STRICT_CONCURRENCY=COMPLETE 的情况下使用 Swift 6
内容大概
Swift 6 引入了许多新功能,我很想使用,但由于严格的并发检查,我的项目(约1万行代码)无法在 Swift 6 模式下成功编译。我确信我的代码是安全且无错误的,并且通过动态手段来保证这一点。我不愿意使用基于 actor 的同步模型,也不打算采用 Swift 的结构化并发。因此,我的目标是迁移到 Swift 6,但不使用“严格并发检查”。
如何在不启用严格并发检查的情况下使用 Swift 6?
你可以通过逐步迁移到 Swift 6,而不必立即启用严格的并发检查。虽然 Swift 6 强制并发检查,但你可以参考 Swift 官方的迁移指南,逐步处理并发问题,而不是一次性解决所有问题。这样做可以让你在使用新特性的同时,避免对现有代码做大规模的修改。
对于全局可变的、非 actor 隔离的变量,可以暂时通过 nonisolated(unsafe)
来避免严格的并发检查。这个注解会告诉编译器,不对这些变量进行并发安全性检查,即使在 Swift 6 模式下也能起作用。这是一个临时解决方案,适合在迁移过程中使用。
未来计划:Swift 6 之后
如果你计划继续使用 Swift 6 的并发特性,最终还是需要迁移到严格的并发检查。即便在短期内通过 nonisolated(unsafe) 绕过了严格检查,长期来看,完全迁移到严格检查模式是非常有必要的。这不仅可以利用编译器的检查功能来避免潜在的并发错误,还可以确保你在 Swift 新的并发模型中不会错过重要的优化和安全机制。
对于大型项目而言,逐步迁移的时间表可能需要一到两年,但在这期间,通过正确的规划和步骤,可以确保迁移过程平稳且可控,最终享受到 Swift 并发模型带来的好处。
内容大概
在 Swift 6 中,编译器不允许 nonisolated 修饰符用于 actor 中的可变存储属性,因为这会导致共享可变状态,这与 Swift 的并发模型相违背。然而,当属性声明为 lazy 时,编译器允许 nonisolated lazy var 的声明,这可能会导致数据竞争问题。
问题分析
lazy 仅影响变量的初始化方式,但在初始化后,属性的行为与普通的 nonisolated var 类似。换句话说,lazy 属性的初始值是延迟计算的,但一旦初始化,后续的读写行为不再受 lazy 修饰符的影响。因此,允许 nonisolated lazy var 可能导致数据竞争,正如以下代码展示的那样:
actor A {
var i = 0
nonisolated lazy var k = 0
nonisolated func readK() -> Int {
k += 1
return k
}
}
func run() {
let a = A()
Task.detached {
let result = a.readK()
print("\(result)")
}
Task.detached {
let result = a.readK()
print("\(result)")
}
}
在这个例子中,nonisolated lazy var k 允许多个任务并发访问 k,导致数据竞争。两个并发任务可能同时读取和修改 k,导致不安全的共享状态,从而违反 Swift 的并发安全原则。
为什么会发生?
lazy 属性的本质是通过隐藏的存储属性来缓存值,编译器为该属性生成一个 getter 和 setter,这看起来像是计算属性。当 lazy 属性标记为 nonisolated 时,编译器可能没有正确处理它背后的存储属性,因此没有触发错误检查。通常,如果这种模式是手动编写的,编译器会拒绝访问这种非隔离的存储属性或阻止 getter。
可能的解决方案:
总的来说,这是一个潜在的编译器问题,可能需要修复。
7) 讨论SDL、游戏循环和 Swift 并发
内容大概
在使用 Swift 并发和 SDL 进行游戏开发时,游戏循环存在一些问题。通常,游戏循环要么是繁忙等待循环,要么是阻塞循环(例如使用 WaitMessage 让线程暂停),这对 Swift 并发机制不友好,因为它会导致主 Actor 执行器集中在游戏循环上,忽视了其他需要调度的任务。
为了解决这个问题,可以在游戏循环中使用 Task.yield(),以便给执行器机会去处理其他任务。这种方法目前看来是可行的。
另一个问题是,Swift 的主 Actor 并不绑定到主线程,这会引发一些问题,因为某些 Win32 API 和第三方库(包括 SDL)要求从主线程调用它们。如果使用 Swift 并发或 DispatchQueue,一旦脱离了真正的主线程,似乎就无法再回到主线程。
此外,线程阻塞也会导致问题。为避免这种情况,可以使用定时器而不是繁忙等待,这样可以避免长时间阻塞主线程,从而避免对 Swift 的任务调度队列产生影响。
摘要: 这篇官方文章讲解了 Swift6 带来了多项重要更新,扩展了语言的功能和平台支持:
@DebugDescription
简化调试,提升调试启动性能。Swift6 进一步提升了跨平台开发和嵌入式应用的能力。
摘要: Swift 的 @resultBuilder 是一项强大的语言特性,允许开发者以声明式的方式构建复杂的数据结构。它常用于创建 DSL、构建 UI 组件和生成配置文件等场景。@resultBuilder 通过静态方法如 buildBlock、buildIf 和 buildEither 等将多个代码块组合成一个结果。本文通过示例展示了如何定义和使用自定义结果构建器,以及它在处理条件语句和构建复杂结构中的应用。该特性可以简化代码、提升可读性,并在实际开发中提高效率。
@inlinable 和 @usableFromInline 内联
摘要: 这篇博客主要介绍了 Swift 中的两个修饰符:@inlinable
和 @usableFromInline
,并详细解释了它们的作用及使用场景。
@inlinable
一起使用时,允许它在其他模块内联使用,不暴露实现细节。文章还分析了 @inlinable
在不同场景中的实际使用方法,指出其可以用于小型、性能关键的代码,但应避免过度使用,以免导致二进制文件膨胀和维护困难。
近期股市经历暴涨后暴跌,专家称因前期涨速过快及市场情绪紧张。业内认为调整非牛市结束,建议投资者保持冷静。你认为今年会有牛市吗?
欢迎在文末留言参与讨论。
Swift社区是由 Swift 爱好者共同维护的公益组织,我们在国内以微信公众号的运营为主,我们会分享以 Swift实战、SwiftUl、Swift基础为核心的技术内容,也整理收集优秀的学习资料。
特别感谢 Swift社区 编辑部的每一位编辑,感谢大家的辛苦付出,为 Swift社区 提供优质内容,为 Swift 语言的发展贡献自己的力量。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。