SwiftUI dismiss返回上一页面时如何传递数据?有哪些实现方案?
SwiftUI 模态页面 dismiss 数据回传可选方案
方案1:闭包回传(和UIKit实现逻辑一致)
你现有的FilterView已经定义了onDismiss回调闭包,只需要在父视图ContentView创建FilterView时给闭包赋值,就能收到回传的Filter数据,修改后的代码如下:
struct ContentView: View { @State var showModel = false // 新增状态存储回传的筛选数据 @State private var receivedFilter: Filter? var body: some View { VStack { // 可选:显示收到的筛选数据 if let filter = receivedFilter { Text("选中区间:\(filter.fromDate) 至 \(filter.toDate)") } Button(action: { showModel.toggle() }, label: { Text("Show filters") }).sheet(isPresented: $showModel, content: { // 给FilterView传入onDismiss的实现逻辑 FilterView(onDismiss: { filter in receivedFilter = filter }) }) } } } // 原有FilterView代码不需要改动 struct FilterView: View { @Environment(\.presentationMode) var presentationMode var onDismiss: ((_ model: Filter) -> Void)? var body: some View { VStack { Button(action: { let filter = Filter(fromDate: "10/07/2021", toDate: "12/07/2021") onDismiss?(filter) presentationMode.wrappedValue.dismiss() }, label: { Text("Applay Filters") }).padding() }.padding() } } struct Filter { var fromDate: String var toDate: String }
该方案适合页面层级浅、仅需要单次回调传值的场景,逻辑和UIKit的闭包回调完全一致。
方案2:@Binding 双向绑定传值
直接把父视图的状态变量通过绑定传到子视图,子视图修改绑定变量时父视图会自动同步更新,不需要手动触发回调,适合需要实时同步状态的场景:
// 父视图部分 .sheet(isPresented: $showModel, content: { FilterView(selectedFilter: $receivedFilter) }) // 子视图FilterView部分 struct FilterView: View { @Environment(\.presentationMode) var presentationMode @Binding var selectedFilter: Filter? var body: some View { VStack { Button(action: { let filter = Filter(fromDate: "10/07/2021", toDate: "12/07/2021") selectedFilter = filter presentationMode.wrappedValue.dismiss() }, label: { Text("Applay Filters") }).padding() }.padding() } }
方案3:EnvironmentObject 环境对象传值
适合多页面、多层级嵌套的视图共享数据的场景,不需要逐层传递闭包或者绑定,只需要把数据模型注入到父视图的环境中,所有子视图都可以直接访问和修改:
// 定义可观察的数据模型 class FilterViewModel: ObservableObject { @Published var selectedFilter: Filter? } // 父视图注入环境对象 struct ContentView: View { @State var showModel = false @StateObject private var vm = FilterViewModel() var body: some View { VStack { if let filter = vm.selectedFilter { Text("选中区间:\(filter.fromDate) 至 \(filter.toDate)") } Button(action: { showModel.toggle() }, label: { Text("Show filters") }).sheet(isPresented: $showModel, content: { FilterView() .environmentObject(vm) }) } } } // 子视图读取环境对象 struct FilterView: View { @Environment(\.presentationMode) var presentationMode @EnvironmentObject var vm: FilterViewModel var body: some View { VStack { Button(action: { vm.selectedFilter = Filter(fromDate: "10/07/2021", toDate: "12/07/2021") presentationMode.wrappedValue.dismiss() }, label: { Text("Applay Filters") }).padding() }.padding() } }
方案4:监听sheet的onDismiss回调(iOS 15+支持)
如果不需要子视图主动触发回调,也可以在父视图监听sheet的消失事件,配合共享状态变量获取数据,适合页面关闭时统一处理逻辑的场景:
struct ContentView: View { @State var showModel = false @State private var tempFilter: Filter? @State private var receivedFilter: Filter? var body: some View { VStack { if let filter = receivedFilter { Text("选中区间:\(filter.fromDate) 至 \(filter.toDate)") } Button(action: { showModel.toggle() }, label: { Text("Show filters") }) .sheet(isPresented: $showModel, onDismiss: { // sheet消失时同步数据 receivedFilter = tempFilter }, content: { FilterView(selectedFilter: $tempFilter) }) } } }
内容的提问来源于stack exchange,提问作者Jessy
相关产品推荐
相关产品推荐

