SwiftUI:DisclosureGroup内按钮弹出.sheet首次展示即消失问题求助
问题原因与解决方案
问题根源
错误提示的核心是DisclosureGroup的展开过渡动画与Sheet的弹出操作发生了并行冲突。当你点击DisclosureGroup内的按钮时,DisclosureGroup的展开状态变更会触发UIKit内部的布局过渡(属于一种presentation类型的操作),此时立刻触发Sheet弹出,系统会检测到「已有一个presentation流程在进行中」,直接中断Sheet的展示,导致Sheet一闪而过并抛出错误。
保留现有设计的解决方案
方案1:延迟Sheet弹出,等待展开动画完成
通过给Sheet的弹出操作加一个短暂延迟,等DisclosureGroup的展开动画结束后再执行:
struct CompositedTestDisclosureGroup: View { @State private var disclosureGroupIsExpanded = false @State private var sheetIsPresented = false var body: some View { TestDisclosureGroup(disclosureGroupIsExpanded: self.$disclosureGroupIsExpanded) { // 延迟0.2秒,适配DisclosureGroup的默认动画时长 DispatchQueue.main.asyncAfter(deadline: .now() + 0.2) { self.sheetIsPresented = true } } .sheet(isPresented: self.$sheetIsPresented) { Text("Test") } } }
方案2:禁用DisclosureGroup的展开动画
如果不需要DisclosureGroup的展开动画,可以直接关闭它,避免并行操作冲突:
struct TestDisclosureGroup: View { @Binding var disclosureGroupIsExpanded: Bool var presentSheet: () -> Void var body: some View { DisclosureGroup("Disclosure Group", isExpanded: self.$disclosureGroupIsExpanded) { Button("Push Me") { presentSheet() } .buttonStyle(.borderedProminent) } // 针对展开状态变更禁用动画 .animation(nil, value: disclosureGroupIsExpanded) } }
方案3:将Sheet绑定到更高层级视图(优化实现)
基于你已知的方案做优化,把Sheet的状态托管在HomeView中,通过绑定传递给子视图,从根源避免子视图内的状态变更与动画冲突:
struct HomeView: View { @State private var sheetIsPresented = false var body: some View { List { CompositedTestDisclosureGroup(sheetIsPresented: $sheetIsPresented) } .sheet(isPresented: $sheetIsPresented) { Text("Test") } } } struct CompositedTestDisclosureGroup: View { @State private var disclosureGroupIsExpanded = false @Binding var sheetIsPresented: Bool var body: some View { TestDisclosureGroup(disclosureGroupIsExpanded: self.$disclosureGroupIsExpanded) { self.sheetIsPresented = true } } }
内容的提问来源于stack exchange,提问作者Ser Pounce
相关产品推荐
相关产品推荐

