历届 WWDC 苹果在研制效率上的改动都让开发者眼前一亮。今年尽管头戴式设备 Vision Pro 占有了大部分 Sessions,但苹果工程团队在 Xcode、构建体系、调试、言语才能等研制效率方向也做出许多更新。其间最让人重视的三个点:

  • 新链接器 ld-prime 的发布,苹果工程师声称比 ld64 快 5 倍。

  • Mergeable libraries:Rlease 构建中使动态库取得相似于静态链接的运用程序发动时刻,而在 Debug 构建中不会损失动态链接的构建时刻。

  • 运用 os_log 在 Debugger Console 取得优秀的日志展现。

Xcode IDE

概览

  • 各平台运转时被分成单独的安装。当你从开发者网站下载 Xcode 或许首次发动 Xcode 时,能够挑选你要开发的平台,有用的减小了包体积。而且你能够随时添加或移除平台运转时。详见安装和管理模拟器运转时。

  • 在Xcode项目设置中访问和装备你的团队经过 App Store Connect 授予的功用。拜见功用。

  • 新的集成菜单来暂存和提交源代码库房的更改,并创立和管理你的 Xcode Cloud 作业流程。

  • 根据你的运用和运用的三方 SDK 中的隐私清单生成运用的隐私陈述,开发人员能够运用 Xcode 来创立一个隐私陈述,汇总运用程序和三方 SDK 中所收集的数据信息。。详见在隐私清单中描述数据运用。

  • 验证项目中 XCFramework 的代码签名。假如签名发生变化或被删去,Xcode 构建体系进行报错。详见验证XCFramework的来历。

示例:新的 Quick Actions 菜单

经过快捷键 Cmd shift + A 呼起 Quick Actions,能够履行多种操作比如说断点操作、导航栏、Refacotr。

Related sessions from WWDC23

Session 10165: What’s new in Xcode 15

Code and build system

概览

  • 更有用地运用代码补全。Xcode 运用更多的输入源进行代码补全,根据上下文进行补全优化,并改进了函数参数显现。

  • Swift 新版别支持宏的运用,Xcode 同样进行了相关适配:在 source editor 中能够查看 Swift 宏的展开形式,并在宏生成的代码中设置断点。有关 Swift 宏的更多信息,请拜见 Applying Macros.。

  • 为代码行创立书签。将书签成组进行安排,并创立待办事项列表,在处理完后能够将项目标记为已完结。

  • 在构建时验证与模块链接的才能。模块验证默许启用,但能够经过设置构建设置中的 Enable Module Verifier 来启用和禁用验证。拜见构建设置参阅。

  • 运用可兼并的动态库,在发布版别中取得相似静态链接的运用发动时刻,而在调试版别中坚持动态链接的构建时刻。拜见装备项目以运用可兼并库。

详解:运用可兼并的动态库

静态库在构建时将代码链接到二进制文件中完结符号抉择,而动态库则在运转时由动态链接器加载。静态库在构建时刻上较慢,但对运用程序的发动时刻没有影响,而动态库则相反。Mergeable libraries 能够实现静态库和动态库两种链接战略的优势。

Mergeable libraries 其原理是针对动态库及其依靠项在构建进程中会生成元数据,这些动态库便能够在 Debug/Rlease 时挑选静态链接或动态链接。兼并后的输出能够是运用程序的二进制文件或其他动态库。

Xcode 中供给了手动敞开和主动敞开两种形式,操作起来十分便利。主动兼并能够兼并一切 Framework 目标的直接依靠项,手动兼并能够准确控制哪些 Framework 需求兼并。

Mergeable libraries 在调试和符号化方面会有所变化。调试形式下,链接器不会兼并库,而且会将库保留在磁盘上以支持迭代开发,这里运用了链接器的 Reexporting 功用保证你只依靠兼并库而能运用一切兼并库直接依靠的 API。 不过在发布形式下会进行兼并。关于符号化,兼并库仍保留了源代码的符号信息,以便进行调试和剖析,不过在 crash 仓库中所展现的 image 是兼并之后的库的路径。

Mergeable libraries 敞开时动态库的 segments 直接链接到二进制中会导致包变大,为了防止这些不必要的符号建议经过 -no_exported_symbols 将没必要的符号进行排除,然后减小运用程序包的巨细。

此外兼并库还会影响 dlopen API 的路径、 Bundle 资源加载。但假如你将 iOS 部署版别升级到 12,这些便不需求担心,官方增加了一个 hook 使 bundle 能正确进行查找,假如你不依靠这个功用能够在新链接器上运用 -no_merged_libraries_hook 来进行关闭。

详解:新链接器 ld-prime

新的链接器在 WWDC 中并没有占有任何篇幅,只是在一些 Session 中几句概过,但是咱们从大家的讨论来看他的功能提高十分明显,Davide Italiano 在 twitter 上提到重写过的链接器比 ld64 要快 5 倍。一些工程上实测也得到了 4 倍的功能提高。

新的链接起在 Xcode15 Toolchain 路径中能够找到,其二进制名为 ld-primer,运用行为同 ld 基本共同。在上层 clang 指令中也能够经过选项 -ld64 切换到 ld64 链接器,经过 -ld_prime 切换到新链接器,默许运用 ld-prime。

新链接器挖掘了并发才能,工程规模越大收益越明显。在 WWDC 官方供给的 Backyard Birds 示例中测验链接时刻从 180ms 降低到 120ms,一些大型工程在 Xcode15 实践下来在链接阶段也有 4 倍的功能提高。各方面的测验数据标明这是一个十分不错的链接器,开发者能够赶快推动 Xcode15 的适配啦!

构建体系上,Xcode 15 会主动为动态库生成 TBD 然后加快增量构建,这个 feature 也是一个十分不错的测验,遗憾的是 WWDC 也没有提及。

Related sessions from WWDC23

Session 10166: Write Swift macros

Session 10268: Meet mergeable libraries

Preview and documentation

  • 运用#Preview Swift 宏为一切UI技术生成预览,生效规模包含 SwiftUI、AppKit、UIKit 和 WidgetKit。

  • Xcode 中运用字符串目录以可视化编辑器本地化和翻译运用程序的一切文本。在一个当地保管翻译、装备不同区域和言语环境的复数消息,并更改文本在不同设备上的显现方式。拜见运用字符串目录进行本地化和多样化文本。

  • 主动为 Assets 资源生成编码符号,这样就不需求经过字符串名称对资源进行引证,然后防止比较多的编译问题。

示例:预览界面

为代码编写的文档能够实时预览。从 Assistant 入口便能够跳转到新的文档预览助手。快速协助供给新的视觉款式,支持图画,并根据您的编辑器字体进行动态字体巨细调整。

DocC 现在支持视频、更多布局装备和主题。

Related sessions from WWDC23

Session 10252: Build programmatic UI using Xcode Previews

Session 10244: Create rich documentation with Swift DocC

Tuning and debugging

概览

  • 运用 os_log 输出的调试信息能够在调试控制台展现结构化的日志。Debug Console 会供给日志的信息来历,还能够按元数据进行过滤。单个日志消息能够跳转到源代码。这些新的功用在 macOS 13.3 及更高版别、iOS 17 及更高版别、iPadOS 17 及更高版别、watchOS 10 及更高版别和 tvOS 17 及更高版别的设备和模拟器运转时可用。

  • 运用 devicectl 指令能够和设备进行交互。该指令能够查看一切衔接设备、经过 CoreDevice 服务衔接设备、对设备衔接失利等情况进行诊断。有关 devicectl 的具体信息,运转 xcrun devicectl help。

  • LLDB 需求记住许多打印变量指令,如”expression”、”v”、”vo”、”frame variable”等,运用时会有挑选困难。因此,引入了 Do What I Mean Print 来简化这个进程。在 Xcode15 之后你直接运用 p var 的方式进行输出,它能够评估多个不同的代码表达式,并以最快的方式回来成果,协助开发人员节省时刻。

示例:devicectl 设备衔接失利问题诊断

设备衔接失利后履行指令 xcrun devicectl diagnose 能够得到以下具体日志

Host System: Finished 'Gather network state'. Results at ifconfig.txt
Host System: Finished 'List information about all devices'. Results at CoreDevice-listDevices.json
Copying CoreDevice database
Host System: Finished 'Copy the Core Device database'. Results at /private/var/folders/b1/0fd1b6hs7lz0fm_mh346lybm0000gn/T/TemporaryItems/NSIRD_devicectl_y8X0a4/devicectl_diagnose_2023_06_12.08-58-24/host/CoreDevice-db.sqlite
Copying DDI version.plists from /Library/Developer/DeveloperDiskImages
ERROR: Host System: 'Copy the DDI version.plists from /Library/Developer/DeveloperDiskImages' failed: The file “DeveloperDiskImages” couldn’t be opened because there is no such file. (NSCocoaErrorDomain error 260.)
         NSFilePath = /Library/Developer/DeveloperDiskImages
         NSURL = file:///Library/Developer/DeveloperDiskImages/
--------------------------------------------------------------------------------
ERROR: The operation couldn’t be completed. No such file or directory (NSPOSIXErrorDomain error 2.)
Copying DDI version.plists from ~/Library/Developer/DeveloperDiskImages
Host System: Finished 'Copy the DDI version.plists from ~/Library/Developer/DeveloperDiskImages'. 
Host System: Finished 'Get CoreDevice version'. 
Host System: Finished 'Get default Xcode version'.
Host System: Finished 'Gather RemotePairing defaults'.
Host System: Finished 'Gather CoreDevice defaults'.
Waiting for tasks to finish:
  - Host System: List preferred DDIs for all platforms
  - Host System: Gather Bonjour adverts
Host System: Finished 'Gather Bonjour adverts'.
Wrote file to /tmp/devicectl_diagnose_2023_06_12.08-58-24.zip

示例:结构化调试日志

经过下面代码咱们能够快速对 OSLog 有个开始的知道:

import OSLog
//  填写 subsystem、catgory 初始化 logger
let logger = Logger(subsystem: "OSLogTest", category: "Account")
func login(password: String) -> Error? {
    var error: Error? = nil
    let username = "kuper"
    logger.info("Logging in user '\(username)'...")
    // ...
    logger.info("Start fetch user info")
    if let error {
        logger.error("User '\(username)' failed to log in. Error: \(error)")
    } else {
        logger.notice("User '\(username)' logged in successfully.")
    }
    logger.error("Network connection failure")
    Swift.print("normal print")
    return error
}

履行代码后调试控制台中以更丰厚的信息对日志进行了展现,鼠标每放置到一行日志便会在右侧展现源代码点击便能够跳转到对应的代码行。除了丰厚的信息展现功用,还有强大的筛选才能,能够按 Type、Subsystem、Category 进行筛选日志。

示例程序中出现报错,经过颜色或许过错类型筛选定位到报错日志,经过 Debug Console 的源码定位才能快速跳转到目标代码,进行代码修改,十分便捷。OSLog 的 API 运用很简单,项目迁移起来十分便利,这个功用在日常开发中运用起来一定会成为开发利器。

Related sessions from WWDC23

Session 10226: Debug with structured logging

Session 10175: Fix failures faster with Xcode test reports

Distribution and continuous integration

概览

Xcode Organizer 简化了运用选项能够更轻松地进行 distribution。用 Xcode Cloud 加快你的作业:经过Xcode Cloud,能够创立一个作业流,在推送代码更改时主动构建和发布运用程序。能够轻松的运用 TestFlight 进行测验发布。

运用 Xcode Cloud 进行 Notarization,开发者能够设置 Notarization 作业流程,并在构建进程中主动进行 Notarization。完结 Notarization 后,能够直接从 Xcode Cloud 下载现已 Notarized 的运用程序。

时至今日,Xcode Cloud 已发布整整两年。从产品上来看 Xcode Cloud 是一个不错的产品同苹果生态深度结兼并有着杰出的体验,但开发者所重视的功能上提高却并没有在该产品中充分体现比如说分布式才能。Xcode Cloud 小结,修修补补又一年。

Related sessions from WWDC23

Session 10224: Simplify distribution in Xcode and Xcode Cloud