SwiftUI绑定ViewModel错误的Alert仅首次显示后续不弹出问题求助
问题原因
- SwiftUI的
alert(isPresented:)触发弹窗的前提是绑定的布尔值产生false → true的状态切换。你当前代码中自定义的hasError绑定的setter为空,点击Alert的OK按钮关闭弹窗时,系统会尝试将绑定值设为false,但这个操作没有同步把ViewModel中的error属性置为nil,导致hasError的getter一直返回true。 - 后续再次发起请求失败时,即使重新给
error赋值,如果新赋值的error和旧值相等,@Published属性不会发出状态更新通知,也就不会产生false → true的状态变化,SwiftUI检测不到状态切换就不会重新弹出Alert。
解决方案
步骤1:修改ViewModel逻辑
每次发起请求前先重置error为空,保证新请求的错误状态可以正常触发状态更新:
class LanguageViewModel: ObservableObject { var subscriptions: Set<AnyCancellable> = [] @Published private(set) var languages: [LanguageItem]? @Published private(set) var error: Error? func get() { // 发起请求前先重置错误状态 error = nil APIService.fetchData() .receive(on: DispatchQueue.main) .sink(receiveCompletion: { [weak self] value in guard let self = self else { return } if case let .failure(error) = value { self.error = error } }, receiveValue: { (data: [LanguageItem]) in self.languages = data }) .store(in: &self.subscriptions) } // 新增错误重置方法,供关闭弹窗时调用 func resetError() { error = nil } }
步骤2:修正Binding逻辑
完善hasError绑定的setter实现,关闭弹窗时同步清空ViewModel的错误状态:
struct ContentView: View { @ObservedObject private var languageViewModel = LanguageViewModel() var body: some View { let hasError = Binding<Bool>( get: { self.languageViewModel.error != nil }, set: { newValue in // 弹窗关闭时重置错误状态 if !newValue { self.languageViewModel.resetError() } } ) Button(action: { self.languageViewModel.get() }) { Text("Hello, World") } .alert(isPresented: hasError) { let message = self.languageViewModel.error?.localizedDescription return Alert(title: Text("Error"), message: Text(message ?? ""), dismissButton: .default(Text("OK"))) } } }
内容的提问来源于stack exchange,提问作者Valerio
相关产品推荐
相关产品推荐

