观察到的var值不正确

时间:2020-09-12 16:00:58

标签: swift

我有一个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")
              }
            }
          }
        }
    }

我不确定自己做错了什么。

1 个答案:

答案 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")
        })
    }
}

如果仅运行该代码,您将看到点击按钮时,“警报”会出现一段时间,然后消失。这似乎是您所追求的(尽管很难说出来)。