前语

本期是 Swift 编辑组收拾周报的第四十期,每个模块已开始成型。各位读者假如有好的提议,欢迎在文末留言。

Swift 周报在 GitHub 开源,欢迎提交 issue,投稿或推荐内容。现在计划每两周周一发布,欢迎情投意合的朋友一同加入周报收拾。

人间万般兵刃,唯有过往伤人最深。Swift社区邀你走出低谷,迈向山巅!

周报精选

新闻和社区:53.5亿美元!传苹果今明两年或将收购2.3万台AI服务器!

提案:阻隔的默许值表达式

Swift 论坛:评论为什么 CaseIterable 比 Set 更快

推荐博文:掌握 swift 中 Preview macro 的用法

论题评论:

在诸多物流行业,你最看好哪一家?

上期论题成果

Swift 周报 第四十期

投票成果显示大多数人更倾向于坚持薪资不变或者期望薪资增加,而只有少数人乐意接受较小起伏的薪资降低。小编以为公司在决议远程办公方针时需求归纳考虑员工的期望和需求。

新闻和社区

53.5亿美元!传苹果今明两年或将收购 2.3 万台 AI 服务器!

Swift 周报 第四十期

10 月 25 日音讯,依据最新的研究显示,苹果公司计划在 2023 年收购约 2000 – 3000 台 AI 服务器,2024 年或将增加至 1.8 万 – 2 万台,收购的首要方针是满足苹果对AI算力的需求,尤其是在练习和推理生成式 AI 方面。

陈述称,苹果首要收购的是英伟达的 HGX H100 8-GPU 体系,由 8 个 H100 SXM5 模块加上 4 个 NVSwitch Chip 在同一个 System board 上。这款 AI 服务器以其强壮的功能和安稳的表现成为业界热门挑选,单台价格高达 25 万美元(约合人民币 183 万元)。

据天风国际分析师郭明錤预测,在 2023 年和 2024 年期间,苹果将分别收购约 6.2 亿美元(约合人民币 45.38 亿元)和 47.5 亿美元(约合人民币 347.7 亿元)的 AI 服务器,总投额资达 53.3 亿美元。尽管出资额巨大,但考虑到苹果的品牌影响力和技能需求,这一投入无疑是值得的。

现在各行各业对 AI 技能应用持续渗透,关于 AI 算力的需求暴增,全球 AI 服务器商场将迎来更大规模的增加。郭明錤也指出,在未来几年中,全球 AI 服务器商场将持续坚持强劲增加,并为相关企业带来更多时机。因而,关于那些想要在这个范畴取得成功的企业来说,关注并积极参加 AI 服务器商场的扩张至关重要。(来源:芯智讯)

TestFlight 让管理测验员变得更加简略

Swift 周报 第四十期

2023 年 10 月 24 日

借助 TestFlight,你可轻松获取有关 App Beta 版的反应,以便放心肠在 App Store 上进行发布。现在,运用 App Store Connect 中经改善的控件,你可更有用地评价测验员的参加度并管理参加情况,以充分运用 Beta 测验。你可按状况和参加度方针 (例如会话、崩溃和反应) 对测验员进行排序,并删去参加度较低的非活泼测验员。你还能够按设备和操作体系进行挑选,乃至挑选相关测验员,以将其增加到新的群组中。

推送告诉控制面板现已推出新交给方针

2023 年 10 月 19 日

推送告诉控制面板现在包含在生产环境中经过 Apple 推送告诉服务 (APNs) 发送的告诉的方针。借助控制面板的直观界面,你能够检查交给状况的聚合视图,深入了解告诉的各种统计数据 (包含基于推送类型和优先级的详细细分)。

咱们在 WWDC23 (简体中文字幕) 公布的推送告诉控制面板,将能协助你轻松地经过 APNs 向 Apple 设备发送测验告诉。

Apple Vision Pro 开发者实验室现已扩展到纽约市和悉尼

2023 年 10 月 17 日

咱们十分振奋能看到世界各地的开发者对 Apple Vision Pro 开发者实验室的等待和热情。很快乐能在此宣布,咱们已在纽约市和悉尼设立新的实验室。欢迎参加咱们的开发者实验室活动,直接在设备上进行测验,与 Apple 专家沟通交流以取得协助,一同探究怎么让你的 visionOS、iPadOS 和 iOS App 在这个激动人心的新渠道上更进一步。咱们还分别在库比蒂诺、伦敦、慕尼黑、上海、新加坡和东京设立了实验室。

提案

正在审查的提案

SE-0410 **Low-Level Atomic Operations ** 提案正在审查。

该提案为标准库增加了一组有限的低级原子操作,包含 C++ 风格的内存排序的原生拼写。咱们的方针是使编写体系级代码的英勇的图书馆作者和开发人员能够直接在 Swift 中构建同步结构。

SE-0411 阻隔的默许值表达式 提案正在审查。

默许值表达式答应用于默许参数和默许存储特点值。当前默许值表达式的 actor 阻隔规矩存在一些问题:存储特点的规矩容许数据竞争,默许参数值的规矩过于约束,而在不同的默许值表达式运用位置之间的规矩彼此对立,导致 actor 阻隔模型更难了解

该提案一致了默许值表达式的 actor 阻隔规矩,消除了数据竞争,经过安全地答应默许值的阻隔来提高表现力。

Swift论坛

  1. 评论查找符号是怎么导入的?

我有一个运用特定 API 的源文件,但没有导入界说它的包。据我所知,在该文件的导入中,即使是传递性的,也不会导入该包。

然而,该文件在构建时“正确”编译(尽管 Xcode 15 的实时编译赞同我的观念,即 API 不应该可见并生成实时错误)。

我正在运用 Xcode,该文件是一个测验,假如其间任何一个对答案有任何影响。

有没有办法能够调试此 API 的导入方式? 除了 import 之外,是否还有其他机制能够让 swift API 可供 swift 源文件运用?

答复

从技能上讲,只有当你想要运用类型的称号时,才需求将其导入到该文件中。 你能够运用该类型的实例,无需:

// main.swift
let calendar = myCalendar()
let currentYear = calendar.component(.year, from: now())
print("It's (currentYear)")
// This all works fine with no errors.
// The type of `calendar` is NSCalendar, but if we had written
//   let calendar: NSCalendar = myCalendar()
// that would be an error.
// file2.swift
import Foundation
func myCalendar() -> NSCalendar {
  return NSCalendar(calendarIdentifier: .gregorian)!
}
func now() -> Date {
  return Date()
}
  1. 评论 @backDeployed 作为 override 运行,而不是仅用于不受支持的渠道版别

自 Xcode 15 和 iOS 17 发布以来,咱们最近一向面对许多令人头痛的问题,因为咱们 @backDeployed 的 API 的意外行为。

长话短说,我发现咱们 @backDeployed 的任何 API 不仅在渠道布置版别“之前”的操作体系上被调用,而且也在渠道布置版别“之后”的操作体系上被调用。

这能够经过单元测验或 playground 来重现:

import UIKit
public extension Locale.LanguageCode {
  @backDeployed(before: macOS 14.0, iOS 17.0, watchOS 10.0, tvOS 17.0)
  var debugDescription: String { // <-- introduced in iOS 17
    get {
      if #available(iOS 17, macOS 14.0, *) {
        return "17"
      }
      return self.identifier
    }
  }
}
func test() {
  let locale = Locale(identifier: "en_US")
  let languageCode = locale.language.languageCode!
  let desc = languageCode.debugDescription
  // ^ This print should yield "en" on iOS 16 & 17
  // but it yields "17" on iOS 17 (proving the @backDeployed API is actually being treated as an override instead thunking to the platform deployed version).
  // You can comment out the @backDeployed `debugDescription` above to see it go back to correct behavior
}
test()

实际上,咱们运用 @backDeployed 来 override 任何咱们喜欢的 API,而不仅仅是向后布置。

这是否能够在 Swift 的错误修复修订版中解决(最好在退出 beta 之前布置到 Xcode 15.1)?

答复

我以为你误解了 @backDeployed 特点的作用以及它的用处。@backDeployed 规划用于完结操作体系顺便的框架。

该特点的规划意图不是为你供给一种为 SDK 中的恣意函数供给你自己的 polyfill 的办法,因而,假如我正确解说了你想要完结的任务,我以为它不会到达你想要的作用 。

在你的示例中,你已为 Locale.LanguageCode 声明了自己的核算特点 debugDescription。 你的声明不会“覆盖”基金会中的声明;它只是作为能够调用的不同函数一起存在于你的模块中。是否在任何给定的调用站点调用你的完结取决于编译器将 debugDescription 静态解析为哪个声明。

假如编译器解析对你的声明的调用,而不是来自 SDK 的调用,那么你的完结上的 @backDeployed 特点将导致编译器宣布对中心 thunk 的调用,该中心 thunk 调用你的原始函数或函数的副本,它不会完结任何有用的事情,因为它是同一模块中的函数,而且原始副本和后备副本将一向具有相同的完结。

  1. 评论新的 SwiftNIO 异步 API

我很快乐与大家共享,咱们刚刚发布了一些软件包的新版别,其间包含全新的异步 API。

一段时间以来,咱们一向致力于新 API 的开发,让它们在 AsyncChannel SPI 后边进行烘焙。 在最新版别中,咱们将 SPI 晋级为安稳的 API。

新异步 API 的方针是让开发人员能够轻松、安全地在 NIO Channels 和 Swift Concurrency 之间树立桥梁。 新 API 的一个重要部分是它们携带有关 ChannelPipeline 的类型信息,一起坚持灵活性,这是经过运用泛型的强壮功能完结的。

你能够在咱们全新的 NIO 和 Swift Concurrency 文章中找到有关新 API 的更多文档。假如你有兴趣阅览更多有关新 API 背面的想法并检查跨包的 API 增加的概述,请随时检查 咱们的开发者文档.

我想指出的一件重要的事情是,新的 API 在事务逻辑和网络之间供给了清晰的关注点分离。

网络协议存在于通道管道中,事务逻辑应直接在通道管道之外的 Swift Concurrency 中完结。 许多现有应用程序都驻留在通道管道内,咱们强烈主张将事务逻辑移出。

咱们迫不及待地想看看社区运用新 API 构建了什么,并等待你的反应!

  1. 评论运用 ArgumentParser 创建指令行东西的正确办法是什么? swift package 或 Xcode 创建 Mac 指令行东西项目?

我信任创建 ArgumentParser 指令行东西的正确办法是:

swift package init --type tool --name MyTool

然后在 Xcode 中翻开 Package.swift。 但是我无法增加这个包:github.com/dominiceggi…

增加依赖项后,“My Mac” target 消失了。

当我从 Xcode 内部创建 macOS 指令行东西项目时,我能够找到 spinner 包并运用它。 假如我增加 ArgumentParser,运行崩溃。

我应该怎么办?

答复

你能够测验分叉 Spinner,更新其软件包清单以运用 Rainbow 4+ ,取决于你的 fork,而不是原始 fork,然后看看有什么问题……

假如没有任何问题,你能够将该更改作为 PR 提交到 Spinner 项目。

  1. 评论[performSelector(“retainCount”)](forums.swift.org/t/performse… “performSelector(“retainCount”)”)

另一个线程提示我一个调用制止的保存计数的问题——或许对调试意图有用。 我知道一些获取目标的保存计数的技能(例如,经过驻留在非 ARC obj-c 文件中的 C 协助程序进行调用,因而能够调用保存计数,即引证线程中显示的技能)或阅览 经过 “withUnsafeBytes” 直接从 Swift 中保存 Swift 目标的原始位。 那么这个基于 performSelector 的其他办法呢?

let obj = NSObject()
let x = obj.perform("retainCount")!
// p x
// (Unmanaged<AnyObject>) {
//  _value = (object = 0x0000000000000002)
// }
print(x) // crash
let y = x.toOpaque() // crash
print(y)
let z = x.takeUnretainedValue() // crash
print(z)
print(obj)

能够对其进行调整以使其工作吗? 它似乎工作正常,回来正确的 UnmanagedObject,我能够经过 “print” 指令在调试器中看到它,但怎么从应用程序中获取它? 我是否需求运用一些 unsafeBitCast 来读取该值?

答复

PerformSelector: 回来一个目标; 它名义上仅用于回来目标的办法,而不是基元。

在 Objective-C 中,你或许能够经过将成果转化为原始类型来滥用它,但假如它不是指针巨细或渠道的调用约好运用不同的寄存器来回来指针与整数,你将得到废物(或更糟)。

我不确定你是否能够在 Swift 中履行此转化,因为 Unmanaged 假定它的确包含有用的目标引证,而且会测验适当地保存和开释它。

  1. 评论为什么 CaseIterable 比 Set 更快
// V1
enum VaccineCodeSet: String {
    case covidModerna = "207"
    case covidBioNTech = "208"
    case covidAstraZeneca = "210"
    case covidNovax = "211"
    case covidJohnson = "212"
    case covidValneva = "213"
    case hepatitesB = "45"
    case whoopingCough = "11"
    case measles = "05"
    case mumps = "07"
    case rubella = "06"
    case chickenpox = "21"
    case tbe = "77"
    case hepatitesA = "85"
    case yellowFever = "184"
    static var allCases: Set<String> = [
        Self.covidModerna.rawValue,
        Self.covidBioNTech.rawValue,
        Self.covidAstraZeneca.rawValue,
        Self.covidNovax.rawValue,
        Self.covidJohnson.rawValue,
        Self.covidValneva.rawValue,
        Self.hepatitesB.rawValue,
        Self.whoopingCough.rawValue,
        Self.measles.rawValue,
        Self.mumps.rawValue,
        Self.rubella.rawValue,
        Self.chickenpox.rawValue,
        Self.tbe.rawValue,
        Self.hepatitesA.rawValue,
        Self.yellowFever.rawValue
    ]
}
printTimeElapsedWhenRunningCode(title: "VaccineCodeSet") {
    if VaccineCodeSet.allCases.contains("184") {
        true
    }
}
// Time elapsed to check: 0.006421875 s.
// V2
enum VaccineCodeCaseIterable: String, CaseIterable {
    case covidModerna = "207"
    case covidBioNTech = "208"
    case covidAstraZeneca = "210"
    case covidNovax = "211"
    case covidJohnson = "212"
    case covidValneva = "213"
    case hepatitesB = "45"
    case whoopingCough = "11"
    case measles = "05"
    case mumps = "07"
    case rubella = "06"
    case chickenpox = "21"
    case tbe = "77"
    case hepatitesA = "85"
    case yellowFever = "184"
}
printTimeElapsedWhenRunningCode(title: "Array") {
    if let code = VaccineCodeCaseIterable(rawValue: "184"),
       IllnessCodeCaseIterable.allCases.contains(code) {
       true
    }
}
// Time elapsed to check:: 0.005916875 s.

为什么 V1 比 V2 慢?

答复

V2 的确还有一项工作要做:从 String 到 enum case。 但这能够优化(在 init(rawValue:) 完结中),因为编译器知道或许的有用字符串的完整调集,因而它终究比哈希查找更快。

事实上,因为所有字符串都很短,它乃至能够作为整数开关来完结,在检查长度后将字符串内容视为多字节整数。

推荐博文

掌握 swift 中 Preview macro 的用法

摘要: 本篇博客介绍了 Swift 中的新功能——预览宏(Preview macro),以及它对开发体验的改善。预览宏能够轻松地将 SwiftUI 视图、UIViewController 或 UIView 实例嵌入到预览中。文章还评论了怎么创建展现不同视图状况的多个预览,并经过传递标题参数来区别它们。此外,它还介绍了预览宏的 traits 参数,能够在预览中显示横向视图或指定尺寸。文章最后提到了怎么将预览宏与 widget 结合运用来展现交互式的 widget 时间线。作者主张开发者能够运用预览宏来改善开发体验,并指出能够创建专门用于规划体系包的预览文件或示例用法的文件。

Xcode 中运用 SPM 和 Build Configuration 的一些坑

摘要: 本文介绍了 Swift 中的值和类型参数包,并结合示例进行了详细解说。类型参数包和值参数包答应你编写一个接受恣意数量具有不同类型参数的通用函数。在 Swift 5.9 中,因为 SE-393、SE-398 和SE-399 的提案,这一新特性得以完结。采用参数包的最明显影响之一是在 SwiftUI 中的10个视图约束现已不存在,这是因为在这些提案之后可完结了可变参数泛型。本文还解说了参数包的解决方案,它们协助咱们编写可重用的代码,防止编写大量的函数重载。从 Swift 5.9 开始,咱们能够运用参数包重写类似的函数。

Swift 中 User Defaults 的读取和写入

摘要: 这篇文章评论了在 Swift 中运用 User Defaults进行读取和写入的办法。User Defaults 是 Swift 应用程序中用于存储在应用程序启动期间坚持不变的偏好设置的首选解决方案。它是一个基于特点列表(plist)文件的键值存储。文章介绍了一些与 User Defaults 工作时的最佳实践,并供给了一些特定的解决方案和主张。其间包含运用应用程序组与其他应用程序和扩展同享 User Defaults,以及类型支持和数据转化的注意事项。此外,文章还介绍了监听 User Defaults 更改的办法,并探讨了一些代替方案,如 Keychain 和 CloudKit。在文章的结束,作者总结了运用 User Defaults 存储偏好设置的好处,并提示读者在需求跨设备访问数据或存储敏感数据时考虑其他解决方案。。

论题评论

10月27日,起家于东南亚的极兔速递正式登陆港交所。此次IPO,发行价12港元/股,市值约1000亿港元,成为港交所2023年迄今开盘市值最高的IPO。在诸多物流行业,你最看好哪一家?

  1. 菜鸟
  2. 顺丰
  3. 京东物流
  4. 极兔

欢迎在文末留言参加评论。

关于咱们

Swift社区是由 Swift 爱好者一起保护的公益组织,咱们在国内以微信公众号的运营为主,咱们会共享以 Swift实战SwiftUlSwift根底为核心的技能内容,也收拾搜集优秀的学习材料。

特别感谢 Swift社区 编辑部的每一位编辑,感谢大家的辛苦付出,为 Swift社区 供给优质内容,为 Swift 言语的发展奉献自己的力气。