SwiftUI中如何在ViewModel收到API成功响应后触发视图关闭?
解决方案
核心思路
你的ViewModel是ObservableObject类型,可以通过@Published属性向视图同步状态,请求完成后修改状态触发视图的关闭逻辑,而非点击按钮时直接执行关闭。
步骤1:改造ViewModel
在ViewModel中新增一个Bool类型的@Published属性,网络请求成功后将其置为true。
class PageViewModel: ObservableObject { // 标记是否需要关闭当前页面 @Published var shouldDismiss = false func fetchNetworkData() { // 原有网络请求逻辑 WebService.shared.requestAPI { [weak self] result in guard let self = self else { return } // 必须切回主线程更新UI相关属性 DispatchQueue.main.async { switch result { case .success(_): // 请求成功,修改状态通知视图关闭 self.shouldDismiss = true case .failure(let error): // 自定义错误处理逻辑,比如弹出提示 print(error.localizedDescription) } } } } }
步骤2:在视图中监听状态变化
在视图中通过onChange修饰符监听上述属性的变化,当属性变为true时执行关闭操作。
struct TargetPageView: View { @Environment(\.presentationMode) var presentationMode @StateObject var viewModel = PageViewModel() var body: some View { Button("发起请求") { // 只触发请求逻辑,不要在这里调用dismiss viewModel.fetchNetworkData() } // 监听ViewModel的状态变化,满足条件时关闭页面 .onChange(of: viewModel.shouldDismiss) { needDismiss in if needDismiss { presentationMode.wrappedValue.dismiss() } } } }
优化说明
- iOS 15及以上版本可以用更精简的关闭API:将环境变量替换为
@Environment(\.dismiss) private var dismiss,关闭时直接调用dismiss()即可。 - 如果页面可能被多次推入导航栈,执行关闭前可以先将
shouldDismiss重置为false,避免重复触发关闭逻辑。
内容的提问来源于stack exchange,提问作者New iOS Dev
相关产品推荐
相关产品推荐

