Sorry for simple question, try to learn SwiftUI
My goal is to show alert then i can not load data from internet using .alert()
the problem is that my struct for error actually has data but it does not transfer to .alert()
debug shows that AppError struct fill in with error but then i try to check for nil or not it is always nil in .Appear()
PostData.swift
struct AppError: Identifiable {
let id = UUID().uuidString
let errorString: String
}
NetworkManager.swift
class NetworkManager: ObservableObject {
@Published var posts = [Post]()
@Published var appError: AppError? = nil
func fetchGuardData() {
if let url = URL(string: "http://hn.algolia.com/api/v1/search?tags=front_page") {
let session = URLSession(configuration: .default)
let task = session.dataTask(with: url) { data, response, error in
if error == nil {
let decorder = JSONDecoder()
if let safeData = data {
do {
let results = try decorder.decode(Results.self, from: safeData)
DispatchQueue.main.sync {
self.posts = results.hits }
} catch {
self.appError = AppError(errorString: error.localizedDescription)
}
} else {
self.appError = AppError(errorString: error!.localizedDescription)
}
} else {
DispatchQueue.main.sync {
self.appError = AppError(errorString: error!.localizedDescription)
}
}
} //
task.resume()
} else {
self.appError = AppError(errorString: "No url response")
}
}
}
ContentView.swift
struct ContentView: View {
@StateObject var networkManager = NetworkManager()
@State var showAlert = false
var body: some View {
NavigationView {
List(networkManager.posts) { post in
NavigationLink(destination: DetailView(url: post.url)) {
HStack {
Text(String(post.points))
Text(post.title)
}
}
}
.navigationTitle("H4NEWS")
}
.onAppear() {
networkManager.fetchGuardData()
if networkManager.appError != nil {
showAlert = true
}
}
.alert(networkManager.appError?.errorString ?? "no data found", isPresented: $showAlert, actions: {})
}
}
>Solution :
Probably when doing this check, the data fetch process is not finished yet.
if networkManager.appError != nil {
showAlert = true
}
So you should wait the network request finish to check if there is error or not.
If you sure there is error and just test this try this to see error:
DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
if networkManager.appError != nil {
showAlert = true
}
}
To handle better this situation you can pass a closure your fetchGuardData function and handle your result and error inside it.
or you can use .onChange for the listen the changes of appError.
.onChange(of: networkManager.appError) { newValue in }