关于使用 SwiftUI 构建 macOS 应用的 WWDC 27 更新

Lobsters Hottest 工具

摘要

本文介绍了 WWDC 27 中 SwiftUI 的改进,用于构建 macOS 应用,涵盖选中状态、拖放和键盘快捷键的新 API。

<p><a href="https://lobste.rs/s/temfk6/wwdc_27_update_on_building_mac_assed_app">评论</a></p>
查看原文
查看缓存全文

缓存时间: 2026/07/13 07:50

# WWDC 27 更新:用 SwiftUI 构建一款 Mac-assed 应用 来源:https://pfandrade.me/blog/swiftui-mac-assed-wwdc27-update/ 我之前那篇关于用 SwiftUI 构建 Mac-assed 应用(https://pfandrade.me/blog/mac-assed-swiftui-app/)的文章,获得的关注度超出了我的预期。它被多次提及:在 Mastodon 上(https://mastodon.social/@stroughtonsmith/116545164468952303)被引用(https://mastodon.social/@stroughtonsmith/116545164468952303/quotes),被收录进 iOS Dev Weekly(https://iosdevweekly.com/issues/750/#fuwtRgx),启发了我五月份的 Swift 博客嘉年华(https://swiftcarnival.github.io/),最终还被 John Gruber(https://mastodon.social/@gruber)——可以说是推广「Mac-assed」这个说法的主要功臣——在 Daring Fireball(https://daringfireball.net/2026/06/swiftui_only_makes_it_easy_to_develop_bad_apps)上提及。 这些关注也引来了 Apple 的一位工程师主动联系我,并给出了一些意见。我们来回了几封邮件,我提交了几个雷达反馈,现在 WWDC 27 已经结束,这篇博文算是对我之前写到的那些问题的一个小更新。 ## 选中状态 关于选中状态,有一个我写上一篇文章时不知道的 `\.backgroundProminence` 环境值(https://developer.apple.com/documentation/swiftui/environmentvalues/backgroundprominence)。 根据文档,「List 和 Table 等视图以及标准的形状样式(如 `ShapeStyle.selection`)会自动更新前景视图的背景突出度。」 这意味着 SwiftUI 已经有一个内置概念,非常接近我所说的 `\.isEmphasized`。如果你在用 `List` 或 `Table`,你可以在选择突出度变化时检查这个值。 当然,如果你没有使用 `List` 或 `Table`——而且如果你要做任何认真的自定义,很可能没有用——我之前提到的方法仍然是可行的方案:自己追踪焦点并通过环境传递状态。 区别在于,你可以复用 `\.backgroundProminence`,而不用再创建自己的 `\.isEmphasized` 值。这样做的一个好处是,如果你的自定义行将来被放到 `List` 或 `Table` 内部,它们的兼容性会更好一些。 我还提交了 FB23095823(https://openradar.appspot.com/FB23095823),其中包含了一些想法,希望 `List` 能够暴露更多能力,让自定义行更有用。我仍然认为这是正确的方向。当你使用 AppKit 或 UIKit 时,你的单元格和行拥有极大的灵活性,我提出的反馈就是试图让 `List` 更接近那种可能性。 ## 拖放 有一个新的 `\.onDragSessionUpdated` API(https://developer.apple.com/documentation/swiftui/view/ondragsessionupdated(_:)),在 27 系列 OS 中引入,并且似乎已经在 macOS 26 上可用,它解决了我对 SwiftUI 拖放的最大痛点:在拖拽开始时就能了解拖拽会话。 我还没有测试过,但理论上它正好填补了缺失的部分。你终于可以在拖拽开始时更新 UI,并在会话结束时可靠地清理,即使拖拽发生在你的视图之外。 这正是 AppKit 已经能够做到的事情,所以看到 SwiftUI 在这方面更接近了,是件好事。 话虽如此,我的应用通常支持最近两个主要 OS 版本,所以我可能要到两年后才会开始使用这个新 API。 另外值得注意的是,在 27 版本中新增的 `\.reorderable` 修饰符(https://developer.apple.com/documentation/SwiftUI/DynamicViewContent/reorderable())。如果你只是想允许重新排序,这应该是首选方法。 ## 键盘快捷键 正如我之前提到的,`\.onMoveCommand` 在 iOS 上不可用。解决方法是使用更低层次的抽象,比如 `\.onKeyPress`,它在 macOS 上同样有效。 这虽然可行,但并不是一回事。`\.onMoveCommand` 是更合适的 API,因为它处理的是意图。我并不是真的关心用户按了向下箭头键,我关心的是用户想要向下移动。 起初我以为 `\.onMoveCommand` 在 iOS 上不可用是因为 `UIResponder` 没有对应的 `move*` 选择器。后来我发现 `\.onMoveCommand` 在 tvOS 上是可用的。 所以我现在又回到了最初的看法:这仅仅是一个 API 可用性的缺口。如果它在 tvOS 上有意义,那么在 iPadOS 上也绝对有意义,因为 iPad 上硬件键盘很常见,方向键导航也是预期功能。 为此我提交了 FB23095985(https://openradar.appspot.com/FB23095985)。这些微小的平台差异恰恰削弱了跨平台 UI 框架的承诺。孤立地看它们很小,但当你试图共享真实的 UI 代码时,它们很快就会累积起来。 ## 其他不满 至于我提到的其他问题,我提交了 FB23097100(https://openradar.appspot.com/FB23097100),关于无法知道上下文菜单当前是否打开;以及 FB23102836(https://openradar.appspot.com/FB23102836),关于改进工具栏 API 的易用性。 上下文菜单的问题对我来说仍然尤其令人沮丧。只有当你没有尝试构建真正的 Mac 界面时,它才像是小问题。在 iOS 上,系统可以视觉上抬起交互中的项目。在 macOS 上,应用需要有足够的信息来自行表示目标。 关于工具栏,WWDC 27 引入了新的 `\.visibilityPriority` 修饰符(https://developer.apple.com/documentation/SwiftUI/ToolbarContent/visibilityPriority(_:)),它有助于管理哪些项目应该优先移到溢出菜单。但这并没有真正解决我的问题,不过我觉得还是应该提一下。

相似文章

在 2026 年使用 SwiftUI 构建纯正的 Mac 应用

Lobsters Hottest

这篇文章讲述了作者完全使用 SwiftUI 构建 macOS 应用的经验,讨论了在实现原生 Mac 体验时遇到的挑战和限制,例如选中状态和非活动窗口的行为,并得出结论:SwiftUI 在 Mac 上尚不足以构建‘纯正 Mac’应用。