来自 ObservableObject class 的数据不会传递给 .alert()
data from ObservableObject class do not pass to .alert()
抱歉,问题很简单,努力学习SwiftUI
我的目标是显示警报,然后我无法使用 .alert() 从 Internet 加载数据
问题是我的错误结构实际上有数据,但它不会传输到 .alert()
调试显示 AppError 结构填充错误,但随后我尝试检查是否为 nil 它在 .Appear()
中始终为 nil
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: {})
}
}
可能在做这个检查的时候,数据获取过程还没有完成。
if networkManager.appError != nil {
showAlert = true
}
所以你应该等待网络请求完成,检查是否有错误。
如果你确定有错误,就测试一下试试这个看看错误:
DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
if networkManager.appError != nil {
showAlert = true
}
}
为了更好地处理这种情况,您可以传递一个闭包给您的 fetchGuardData 函数,并在其中处理您的结果和错误。
或者你可以使用.onChange来监听appError的变化。
.onChange(of: networkManager.appError) { newValue in }
抱歉,问题很简单,努力学习SwiftUI
我的目标是显示警报,然后我无法使用 .alert() 从 Internet 加载数据 问题是我的错误结构实际上有数据,但它不会传输到 .alert() 调试显示 AppError 结构填充错误,但随后我尝试检查是否为 nil 它在 .Appear()
中始终为 nilPostData.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: {})
}
}
可能在做这个检查的时候,数据获取过程还没有完成。
if networkManager.appError != nil {
showAlert = true
}
所以你应该等待网络请求完成,检查是否有错误。
如果你确定有错误,就测试一下试试这个看看错误:
DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
if networkManager.appError != nil {
showAlert = true
}
}
为了更好地处理这种情况,您可以传递一个闭包给您的 fetchGuardData 函数,并在其中处理您的结果和错误。
或者你可以使用.onChange来监听appError的变化。
.onChange(of: networkManager.appError) { newValue in }