一周前,我在用 SwiftUI 做 macOS App 的时候,发现了一个兼容问题:即实现全尺寸窗口内容在不同的系统版本和不同的 Xcode 版本不一致的情况。

简单地说,我有一个开启了 Full Size Content View 的 NSWindow,通过 NSHostingController 的形式载入了一个 SwiftUI View,但是效果并不一致。有的搭配是 Full Size Content View,有的搭配却不是:

  • Big Sur + Xcode 12.1:正常
  • Catalina + Xcode 12.1:不正常
  • Big Sur + Xcode 12.2 beta 3:不正常
  • Catalina + Xcode 12.2 beta 3:不正常

SwiftUI Full Size Content View-1.png

正常的情况

SwiftUI Full Size Content View-0.png

不正常的情况

直觉告诉我这是 Xcode 12.2 beta 3 的问题,于是汇报给了 Apple。一周后的今天,Apple 给了我答复:

The title bar area on a window is part of the safe area. If you would like a SwiftUI view to render into that area, you will need to add either the ignoresSafeArea() (macOS 11.0) or edgesIgnoringSafeArea() (macOS 10.15) modifier. This will allow that view to render into the titlebar area.

For example:

Text("Hello, world!")
        .foregroundColor(.white)
        .frame(width: 400, height: 400)
        .background(Color.blue.ignoresSafeArea())

Additionally, if using the SwiftUI App lifecycle, all windows should have a full size content area, regardless of the WindowStyle used.

总结

我所认为的「Big Sur + Xcode 12.1」正常的情况,恰恰是不正常的。在 SwiftUI 完善后,Window 将不管设置什么 WindowStyle,统一对待 View,于是我们就可以像处理 iOS 的 SafeArea 一样去处理是否要 Full Size Content 了。可以慢慢把 AppKit 那套机制给忘记了,因为 SwiftUI 迟早可以通过自己的方式来达到各种之前写各种 AppKit 代码才能做到的效果。