为什么iOS 15中的模糊效果会导致状态栏崩溃?

6
自从iOS 15发布以来,我遇到了一个奇怪的问题:我的应用程序根视图上有一个模糊效果(Blur Effect),这取决于场景(phase)。这一切都很完美,直到iOS 15发布为止。现在,每当模糊效果是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")
        }
    }
}

这段代码在iOS 14及之前版本上运行良好,但是自从iOS 15以后出现了以下的bug:

Bug Preview

  • 奇怪的是,当scenePhase变成inactive时,导航栏瞬间跳到了正确的位置。而当scenePhase再次变为active时,它又跳回到状态栏后面的顶部。
  • 此外,当将active scenePhaseBlur Radius更改为0.001而不是0时,一切都正常工作,导航栏不会跳到状态栏后面。

有人知道这种使用模糊效果时可能引起这种奇怪行为的原因吗?

提前感谢您的帮助。


你尝试使用一些堆栈而不是“Group”了吗? - Asperi
你问了“为什么”,所以我们不是苹果的SwiftUI团队(至少我不是),那么我们怎么可能回答为什么呢!也许你需要问如何解决这个问题。 - ios coder
@swiftPunk 好的,我的问题是如何修复这个行为。 - christophriepe
@Asperi 我刚刚用 ZStack 替换了 Group,但这并没有解决问题。此外,在 Group 对象内部是一个 if-else 语句,而不仅仅是一个单独的视图。 - christophriepe
2个回答

3

我曾经遇到过这个问题,但是无法找到解决方法,所以现在我正在使用这个替代方案,它基本上做了同样的事情:

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

这将在您的视图上覆盖一个模糊的矩形。所以在您的情况下:
struct RootView: View {
    @Environment(\.scenePhase) var scenePhase

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

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


1

虽然我不确定这个解决方案是否比其他方案更好,但由于其简单性,我建议考虑它。

之前的

.blur(someCondition ? 2.0 : 0.0)

巧妙的“修复”

.blur(someCondition ? 2.0 : 0.0001)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接