My app consumes few API endpoints to fetch data, that is managed by respective ViewModels.
For example, this ViewModel fetch the languages
class LanguageViewModel: ObservableObject {
var subscriptions: Set<AnyCancellable> = []
@Published private(set) var languages: [LanguageItem]?
@Published private(set) var error: Error?
func get() {
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)
}
}
and so on.
Now for the main UI
struct ContentView: View {
@ObservedObject private var languageViewModel = LanguageViewModel()
var body: some View {
let hasError = Binding<Bool>(
get: { self.languageViewModel.error != nil },
set: { _ in }
)
Button(action: {
self.languageViewModel.get()
}) {
Text("Hello, World")
}
.alert(isPresented: hasError) {
let message = self.languageViewModel.error?.description
return Alert(title: Text("Error"), message: Text(message ?? ""), dismissButton: .default(Text("OK")))
}
}
}
If somehow the API call fails on clicking the button, the first and only first time the alert is shown, then on subsequent clicks does not appear.
Placing a breakpoint on .alert
show that the code is running correctly, just not showing again.
Please send help!!
CodePudding user response:
On alert dismiss button action reset error back to nil, like:
.alert(isPresented: hasError) {
let message = self.languageViewModel.error?.description
return Alert(title: Text("Error"), message: Text(message ?? ""), dismissButton: .default(Text("OK")) {
self.languageViewModel.error = nil // << here !!
})
}