Sheet关闭后Root View的onAppear未触发问题咨询
解决SwiftUI Sheet关闭后Root View onAppear不触发的问题
问题原因
SwiftUI的onAppear仅在视图首次加载、从后台返回前台,或是视图从层级中移除后重新添加时触发。模态Sheet弹出时,Root View并未被销毁,只是被覆盖在下层,因此关闭Sheet时不会触发Root View的onAppear。
解决方案
由于Sheet可在多处打开,我们需要绑定当前视图的状态变化,而非依赖Sheet的onDismiss来执行视图专属操作,以下两种方案均可实现:
方案1:自定义Binding监听状态变化
通过自定义Binding,在toggle值从true切换为false时执行视图专属逻辑:
struct ContentView: View { @State private var toggle = false private var sheetBinding: Binding<Bool> { Binding( get: { toggle }, set: { newValue in toggle = newValue // Sheet关闭时(newValue为false)执行操作 if !newValue { handleSheetDismiss() } } ) } var body: some View { Button("\(toggle ? "Hide" : "Show")") { toggle.toggle() } .sheet(isPresented: sheetBinding) { Text("Hello, World!") } .onAppear { print("body.onAppear") } } private func handleSheetDismiss() { // 这里编写当前视图专属的操作,比如刷新数据、更新UI状态等 print("ContentView: Sheet closed, executing view-specific action") } }
方案2:使用ObservableObject结合onChange
如果需要更复杂的状态管理,可借助ObservableObject配合onChange修饰符监听状态变化:
class ViewModel: ObservableObject { @Published var showSheet = false } struct ContentView: View { @StateObject private var viewModel = ViewModel() var body: some View { Button("\(viewModel.showSheet ? "Hide" : "Show")") { viewModel.showSheet.toggle() } .sheet(isPresented: $viewModel.showSheet) { Text("Hello, World!") } .onChange(of: viewModel.showSheet) { oldValue, newValue in // 当状态从true变为false时执行操作 if oldValue && !newValue { handleSheetDismiss() } } .onAppear { print("body.onAppear") } } private func handleSheetDismiss() { print("ContentView: Sheet closed, executing view-specific action") } }
方案优势
两种方案均无需依赖Sheet的onDismiss,操作逻辑绑定在当前视图的状态变化上,无论Sheet从应用何处打开,只要当前视图的Sheet展示状态变为关闭,就会自动执行专属操作,完全符合视图专属逻辑的需求。
内容的提问来源于stack exchange,提问作者Boyan Pavlov
相关产品推荐
相关产品推荐

