PAYATHON 2026

iOS 26 中 .presentationDetents 为什么会改变 sheet 层级?

数据小陈

结论

根据复现结果,这可能是 iOS 26.0 / 26.1 上 SwiftUI detent sheet 的显示层级异常:添加 .presentationDetents([.medium]) 后,根视图的背景或覆盖层会显示在 sheet 上方。iOS 18.5、18.6 及更早版本没有出现这一情况。不过,这份复现报告无法确认 Apple 是否已将其认定为系统回归,也无法确定具体原因。

.zIndex 无效并不意外。根视图和 .sheet 位于不同的呈现层级,调整同一视图层级中的顺序未必能改变 sheet 的系统呈现顺序。报告中的最小复现如下:

ZStack {
    Color.red.opacity(0.3)
    Button("Show") { show = true }
}
.sheet(isPresented: $show) {
    Text("Sheet")
        .presentationDetents([.medium])
}

可用的规避方式

如果需要避免根视图背景覆盖内容,同时不依赖系统 sheet 的拖拽和 detent 行为,可以先不用 .sheet,改为在同一个 ZStack 中自行显示底部面板。下面的示例将面板放在视图树中靠后的位置,使它显示在背景和按钮上方:

struct LoginScreen: View {
    @State private var show = false

    var body: some View {
        ZStack(alignment: .bottom) {
            Color.red.opacity(0.3)
                .ignoresSafeArea()

            Button("Show") {
                show = true
            }

            if show {
                Color.black.opacity(0.3)
                    .ignoresSafeArea()
                    .onTapGesture {
                        show = false
                    }

                VStack {
                    Text("Sheet")
                    Button("Close") {
                        show = false
                    }
                }
                .frame(maxWidth: .infinity)
                .frame(height: 360)
                .background(.regularMaterial)
                .clipShape(
                    UnevenRoundedRectangle(
                        topLeadingRadius: 20,
                        topTrailingRadius: 20
                    )
                )
            }
        }
    }
}

这是自定义面板,不会自动具备系统 sheet 的拖动手势、detent 切换和无障碍呈现等行为,需要根据产品需求自行补齐。如果这些系统能力不可替代,当前报告没有提供经过验证的原生 sheet 修复办法。可以先移除 .presentationDetents,确认显示层级是否恢复,再在目标系统版本上验证后续更新是否改变了表现。

注意事项

.presentationBackground 用于设置 sheet 自身的背景外观,未经验证时不应将它视为根视图覆盖问题的修复办法。调整 .zIndex 或改用 .overlay 也不能保证问题会消失,因为报告中这两种方式都没有改变结果。排查时,应使用相同的最小视图结构,分别在目标 iOS 版本和真机环境中验证。

备注:内容仅供参考。