为什么从 iOS 15 开始,iOS 状态栏会因为模糊效果而崩溃?

chr*_*epe 6 xcode uikit ios swift swiftui

从那时起我遇到了一个奇怪的问题iOS 15:我有一个Blur Effecton App's Root View,它根据scenePhase. 在 iOS 15 发布之前,这一功能一直运行良好。现在,每当Blur Effect为 0 时,Status Bar应用程序的 就会崩溃并且Navigation Bar向上移动并且不再具有交互性。

struct RootView: View {
    @Environment(\.scenePhase) var scenePhase
    @State private var blurRadius: CGFloat = 0

    var body: some View {
        Group {
            OtherViews()
        }
        .blur(radius: blurRadius)
        .onChange(of: scenePhase) { newValue in updateBlurRadius(newValue) }
    }

     private func updateBlurRadius(_ scenePhase: ScenePhase) {
         switch scenePhase {
             case .active : withAnimation { blurRadius = 0 }
             case .inactive: withAnimation { blurRadius = 16 }
             case .background: withAnimation { blurRadius = 16 }
             @unknown default: print("Unknown Case")
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

这段代码在过去和现在都运行良好iOS 14。然而,自从 以来iOS 15,出现了以下错误:

错误预览

  • 奇怪的是,当scenePhase变为 时inactiveNavigation Bar立即跳到正确的位置。一旦再次scenePhase变为active,它就会跳回到 后面的顶部Status Bar
  • 另外,当将 的 更改Blur Radiusactive scenePhase0.001 而不是 0 时,一切都工作得很好,并且Navigation Bar不会跳到 后面Status Bar

有谁知道在使用时会导致这种奇怪行为的原因是什么Blur Effects

非常感谢您提前的帮助。

wak*_*kel 3

我遇到了这个确切的问题,但无法找到解决方案,所以我现在使用这个替代实现,它的作用几乎相同:

ZStack {
    // View to be blurred goes here
    Rectangle()
        .ignoresSafeArea()
        .foregroundStyle(.ultraThinMaterial)
        .opacity(/* Your condition */ ? 1 : 0)
        .animation(.easeInOut(duration: 0.2))
}
Run Code Online (Sandbox Code Playgroud)

这将在您的视图上覆盖一个模糊的矩形。所以在你的情况下:

struct RootView: View {
    @Environment(\.scenePhase) var scenePhase

    var body: some View {
        ZStack {
            OtherViews()
            Rectangle()
                .ignoresSafeArea()
                .foregroundStyle(.ultraThinMaterial)
                .opacity(scenePhase != .active ? 1 : 0)
                .animation(.easeInOut)
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

由于此解决方案使用新材料,因此仅适用于 iOS 15。您可以使用它if #available(iOS 15, *)来提供两种不同的实现,一种适用于 iOS 15+,另一种适用于 iOS 14 及更早版本。