灵动岛是 iPhone14 出现之后的独特设备特性,目前存在的设备类型有 iPhone 14 Pro、iPhone 14 Pro Max、iPhone15 全系列。在 SwiftUI 一些需要忽略安全布局 ignoreSafeArea 的情况下或者需要围绕灵动岛做一些特性时,需要识别 iPhone 设备是否是灵动岛设备。

使用 safeAreaInsets 来检测灵动岛

  1. 根据Apple 的官方 Live activity 文档,我们只能检测设备是否支持Live activity,但不知道设备是否有动态岛
  2. 我使用窗口safeAreaInsets值来检测灵动岛。当设备方向为纵向时,safeAreaInsets.top等于59(显示缩放默认值), 或51(显示缩放大文本)。
  3. 这应该可以支持 iPhone系列之后的型号。

用法:print(UIDevice.current.hasDynamicIsland)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
extension UIDevice {

// 在sceneDidBecomeActive之后获取这个值
var hasDynamicIsland: Bool {
// 1. dynamicIsland只支持iPhone
guard userInterfaceIdiom == .phone else {
return false
}

// 2. 获取 window key,在 sceneDidBecomeActive 之后
guard let window = (UIApplication.shared.connectedScenes.compactMap { $0 as? UIWindowScene }.flatMap { $0.windows }.first { $0.isKeyWindow}) else {
print("Do not found key window")
return false
}

// 3.当设备方向为纵向时,它依然可以正常工作
return window.safeAreaInsets.top >= 51
}
}

也可以使用Device框架并在扩展中实现一个额外的计算属性来检测动态岛的可用性,但是Device框架是穷举,更新并不及时,所以兼容性并不是很高。