I am new to swiftUI. I have one application in which i am making api call, in this application i want to display error if API does not return the response. When i navigate first time to the screen, it displays alert message, but when i go back to previous screen and again navigate back to same screen. alert is not displayed.
struct DashboardView: View {
@ObservedObject var viewModel = DashboardViewModel()
@State private var showingAlert = true
init() {
UINavigationBar.appearance().titleTextAttributes = [.foregroundColor: UIColor.black]
self.showingAlert = true
}
var body: some View {
ZStack {
Color.white
if case .LOADING = viewModel.currentState {
loaderView()
.onAppear(perform: viewModel.getDashboardData)
} else if case .SUCCESS(let dashboard) = viewModel.currentState {
ScrollView(.vertical, showsIndicators: false) {
VStack(alignment: .leading, spacing: 10) {
HStack {
Text("Date:")
.foregroundColor(Color.black)
Text(dashboard.date)
.foregroundColor(Color.black)
}
VStack(alignment: .leading) {
Text("HDURL:")
.foregroundColor(Color.black)
Text(dashboard.hdurl)
.foregroundColor(Color.black)
}
HStack {
Text("Media Type:")
.foregroundColor(Color.black)
Text(dashboard.mediaType)
.foregroundColor(Color.black)
}
HStack {
Text("Service Version:")
.foregroundColor(Color.black)
Text(dashboard.serviceVersion)
.foregroundColor(Color.black)
}
VStack(alignment: .leading) {
Text("Title:")
.foregroundColor(Color.black)
Text(dashboard.title)
.foregroundColor(Color.black)
}
VStack(alignment: .leading) {
Text("url:")
.foregroundColor(Color.black)
Text(dashboard.url)
.foregroundColor(Color.black)
}
VStack(alignment: .leading) {
Text("Explanation:")
.foregroundColor(Color.black)
Text(dashboard.explanation)
.foregroundColor(Color.black)
}
}
.padding(.horizontal, 10)
.padding(.top, UIApplication.shared.keyWindow!.safeAreaInsets.top )
}
.padding(.top, UIApplication.shared.keyWindow!.safeAreaInsets.top )
} else if case .FAILURE(let error) = viewModel.currentState {
VStack {
Text("No Data")
.foregroundColor(Color.black)
}
}
}
.navigationBarTitle("Dashboard", displayMode: .inline)
.alert(item: $viewModel.appError) { appAlert in
Alert(title: Text("Error"),
message: Text("""
\(appAlert.errorString)
Please try again later!
"""
)
)
}
.ignoresSafeArea(.all)
}
}
enum ViewStateDashboard { case START case LOADING case SUCCESS(dashboardModel: Dashboard) case FAILURE(error: String) }
protocol FetchDashboardDataFromServer { func getDashboardData() var currentState: ViewStateDashboard { get set } }
class DashboardViewModel: ObservableObject, FetchDashboardDataFromServer {
struct AppError: Identifiable {
let id = UUID().uuidString
let errorString: String
}
@Published var appError: AppError?
let monitor = NWPathMonitor()
let monitorPostUser = NWPathMonitor()
let queue = DispatchQueue(label: "InternetConnectionMonitor")
var cancelable: Set<AnyCancellable> = []
@Published var currentState: ViewStateDashboard = .START
init() {
self.currentState = .LOADING
}
// GET Method
func getDashboardData() {
print("fetch dashboard data")
self.currentState = .LOADING
monitor.pathUpdateHandler = { pathUpdateHandler in
if pathUpdateHandler.status == .satisfied {
APIClient.dispatch(
APIRouter.GetDashboardData(queryParams:
APIParameters.GetDasbhboardParams(apikey: "bWrk8rdLvkzZG5fHgMBQfU9t0xYFdhC6jOT5UKsY")))
.sink { completion in
switch completion {
case .finished:
print("Execution Finihsed dashboard.")
case .failure(let error):
DispatchQueue.main.async {
print("dashboard error", error)
self.appError = AppError(errorString: error.localizedDescription)
self.currentState = .FAILURE(error: error.localizedDescription)
}
}
}
receiveValue: { dashboardData in
print("received dashboard data", dashboardData)
self.currentState = .SUCCESS(dashboardModel: dashboardData)
}.store(in: &self.cancelable)
} else {
DispatchQueue.main.async {
self.currentState = .FAILURE(error: StringConstants.NoInterNet)
self.appError = AppError(errorString: StringConstants.NoInterNet)
print("no internet get users")
}
}
}
monitor.start(queue: queue)
}
}
What could be the issue here? Any help would be appreciated.
CodePudding user response:
When you close the alert, viewModel.appError
is set to nil
. If you want it to appear again, you must set it to a value again.