我正在寻找一个纯粹的基于SwiftUI的解决方案,以确定iOS设备是否有一流的基础上的根视图的安全区插图.虽然这在UIKit中很容易确定,但对于SwiftUI,到目前为止我找到的唯一解决方案也是UIKittish,即:

extension UIApplication {
     var currentWindow: UIWindow? {
       connectedScenes
         .compactMap {
             $0 as? UIWindowScene
         }
        .flatMap {
            $0.windows
         }
        .first {
            $0.isKeyWindow
        }
    }
 }

 private struct SafeAreaInsetsKey: EnvironmentKey {
    static var defaultValue: EdgeInsets {
      UIApplication.shared.currentWindow?.safeAreaInsets.swiftUiInsets ?? EdgeInsets()
  }
 }
 
extension EnvironmentValues {
   var safeAreaInsets: EdgeInsets {
      self[SafeAreaInsetsKey.self]
   }
}

private extension UIEdgeInsets {
    var swiftUiInsets: EdgeInsets {
      EdgeInsets(top: top, leading: left, bottom: bottom, trailing: right)
   }
 }

虽然SwiftUI很可能会在幕后继续使用UIKit元素,如UIWindow,因此上面的解决方案将在future 几年继续工作,但我仍然想知道是否有一个纯粹的基于SwiftUI的解决方案来解决这个问题.

推荐答案

你可以从GeometryReader获得安全区域插图.您可以将GeometryReader放在视图层次 struct 的最顶端,也可以直接放在WindowGroup { ... }中.然后,您可以向下发送带有环境密钥的插图.

WindowGroup {
    GeometryReader { geo in
        // putting the text directly in a GeometryReader makes it align to the top left
        // which is why I am nesting it in a ZStack that covers the whole screen here
        // any other view that fills all the available space works too
        ZStack {
            ContentView() // the rest of the app is here 
                .environment(\.safeAreaInsets, geo.safeAreaInsets)
        }.frame(maxWidth: .infinity, maxHeight: .infinity)
    }
}
struct ContentView: View {
    @Environment(\.safeAreaInsets) var insets
    var body: some View {
        Text("\(insets.top)")
    }
}

private struct SafeAreaInsetsKey: EnvironmentKey {
    static var defaultValue: EdgeInsets = .init()
}

extension EnvironmentValues {
    var safeAreaInsets: EdgeInsets {
        get { self[SafeAreaInsetsKey.self] }
        set { self[SafeAreaInsetsKey.self] = newValue }
    }
}

请注意,您需要预览整个GeometryReader个,才能在Xcode预览中工作.可以将几何体读取器和ZStack封装到视图修改器中,如下所示,以便可以在预览中方便地使用它:

extension View {
    func readSafeAreaInsets() -> some View {
        GeometryReader { geo in
            ZStack {
                self.environment(\.safeAreaInsets, geo.safeAreaInsets)
            }.frame(maxWidth: .infinity, maxHeight: .infinity)
        }
    }
}

#Preview {
    ContentView().readSafeAreaInsets()
}

Ios相关问答推荐

如何在wiftUI中管理导航栈?

如何在不将应用程序留在SwiftUI上的情况下更改语言?

许多文本字段的性能问题

clang:错误:SDK 路径中不包含libarclite

swiftui动画如何实时确定不对称过渡

iOS 16 堆栈视图中按钮的奇怪动画

卡在 Apple 的 SwiftUI 教程第 5 章(更新应用数据)

弹出视图后使所有背景 UI 模糊

类型任何视图不能符合具有泛型的协议上的视图

在 tableview 中下载图像缩略图时如何提高滚动性能

将flutter android项目导入iOS

在 Swift 中为 UITextField/UIView 摇动动画

在 iPhone 中将 UIViewController 显示为弹出窗口

UIButton 事件.有什么不同?

SwiftUI NavigationView navigationBarTitle LayoutConstraints 问题

以编程方式 Select UITextField 中的所有文本

使用 Chrome DevTools 调试 iOS 6+7 Mobile Safari

UICollectionView flowLayout 没有正确包装单元格

iOS 中的 Google Analytics SDK 3.0 _sqlite3 链接器错误

zoom UIButton 动画 - Swift