我有一个Published
变量,可以在该类中进行设置,但在调用它的视图中不会读取该值。
这是课程:
class Api: ObservableObject {
@Published var showingAlert = false
func getRunClub(url: String, completion : @escaping ([RunClubsv2])->()){
let session = URLSession(configuration: .default)
session.dataTask(with: URL(string: url)!) { (data, response, err) in
if err != nil{
print("Unable to get data \(err!.localizedDescription)")
return
}
//decoding JSON
do {
self.showingAlert = true. <== Here's where I set it
print("Class API set alert to: \(self.showingAlert)") <== I can see it being set to true here
let runclubs = try JSONDecoder().decode([RunClubsv2].self, from: data!)
// print(runclubs)
//returning data
completion(runclubs)
}
catch{
print("Catching error \(error)")
}
}
.resume()
}
我认为它已声明为@ObservedObject var foo = Api()
代码的要旨是:
struct RunClubV2: View {
@ObservedObject var foo = Api()
var body: some View {
VStack{
Text("test")
}
.onAppear{
print("We're going to make the API call for data: \(self.foo.showingAlert)")
Api().getRunClub(url: "URL Here")
{ (runclubs) in
print("Alert was set to: \(self.foo.showingAlert)") <== Here the value is set to false.
if self.foo.showingAlert == true {
print("Show Alert")
}
}
}
}
}
我不确定自己做错了什么。
答案 0 :(得分:2)
每次您说Api()
时,这都是一个不同 API对象。因此,当您说Api().getRunClub
时,您要调用其getRunClub
的Api与您在完成处理程序中检查的Api self.foo
是不同的。好像您将一条狗涂成红色,然后转身想知道为什么这只 other 狗也不是红色。
另外,你所说的事实
print("Alert was set to: \(self.foo.showingAlert)")
if self.foo.showingAlert == true {
都是错误的。该价值不会改变。拥有可观察对象的关键是您观察。您没有观察到它,只是看着它一次。因此,当然,它永远不会改变。
您似乎想做的是执行一些耗时的操作(如联网),在该操作期间发出警报,然后在操作结束时再次取消警报。在这种情况下,您的结构是完全错误的。您需要对ObservableObject的@Published
值使用 binding 来触发警报的存在或不存在。这是您需要的结构的草图示例:
class AlertShower : ObservableObject {
@Published var showAlert = false
func doYourThing() {
self.showAlert = true
// pretend this is your time-consuming operation
DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
self.showAlert = false
}
}
}
struct ContentView: View {
@ObservedObject var alertShower = AlertShower()
var body: some View {
Button("Tap me") {
self.alertShower.doYourThing()
}.fullScreenCover(isPresented: self.$alertShower.showAlert, content: {
Text("I am the alert")
})
}
}
如果仅运行该代码,您将看到点击按钮时,“警报”会出现一段时间,然后消失。这似乎是您所追求的(尽管很难说出来)。