user17864647
user17864647

Reputation: 310

.onRecieve in swift not working as described

@EnvironmentObject var v: Variables


if !isActiveView {
 VStack {

}    
 .onReceive(v.$AllAirplanes) { plane in
          if plane != [] {
            DispatchQueue.main.asyncAfter(deadline: .now() + 3.0) {
              withAnimation(Animation.easeOut(duration: 1.0)) {
                isAnimation.toggle()
              }
            }
            DispatchQueue.main.asyncAfter(deadline: .now() + 3.8) {
              withAnimation {
                isActiveView.toggle()
                locationViewModel.getUserLocation()
              }
            }
          }
        }
}

This is my code. I am getting v.$AllAirplanes from firebase and trying to get my loading screen to keep going until the variable does not equal []. The problem is that it only tests once, so I'm forever stuck on the loading screen, even if the value changes.

From what I've read, I thought OnReceive was how, and the best way to do this. Should I go about this another way?

Edit: I'm updating v.AllAirplanes with this function -


@StateObject var v = Variables()


  func getAllAirplanes() {
    db.collection("Airplanes")
        .addSnapshotListener { querySnapshot, error in
          guard (querySnapshot?.documents) != nil else {
                print("Error fetching documents: \(error!)")
                return
            }
            v.AllAirplanes.removeAll()
            for document in querySnapshot!.documents {
              print("\(document.documentID) => \(document.data())")
              //GET DATA AND SET TO VARIABLE
              v.AllAirplanes.append(document.documentID)
            }
          v.AllAirplanes.remove(object: "Simulator")
          //v.AllAirplanes.append("-Please select an airplane-")
print(
"""
------------------------------
All Airplanes: \(v.AllAirplanes)
------------------------------
"""
)
        }
  }

and this is my class -

class Variables: ObservableObject {
    @Published var AllAirplanes: String<Array> = []
}

Upvotes: 1

Views: 331

Answers (1)

Here is my test example code that shows .onRecieve working as expected.

class Variables: ObservableObject {
    @Published var AllAirplanes: [String] = ["1","2","3"]
}

struct TestingView: View {
    @EnvironmentObject var v: Variables
    
    @State var isActiveView = false
    @State var isAnimation = false
    
    var body: some View {
        // for testing, wait 2 secs then click the button
        Button(action: {
            // change AllAirplanes 
            v.AllAirplanes.append(UUID().uuidString)
            isActiveView.toggle()
        }) {
            Text("Test change AllAirplanes (wait 2 seconds first)")
        }
        
        if !isActiveView {
            VStack {
                Text("TestingView")
            }
            .onReceive(v.$AllAirplanes) { plane in
                print("-----> in onReceive plane: \(plane)")
                if plane != [] {
                    DispatchQueue.main.asyncAfter(deadline: .now() + 1.0) {
                        withAnimation(Animation.easeOut(duration: 1.0)) {
                            isAnimation.toggle()
                        }
                    }
                    DispatchQueue.main.asyncAfter(deadline: .now() + 2.0) {
                        withAnimation {
                            isActiveView.toggle()
                            //  locationViewModel.getUserLocation()
                        }
                    }
                }
            }
        }
    }
}

struct ContentView: View {
    @StateObject var v = Variables()
    
    var body: some View {
        TestingView().environmentObject(v)
    }
}

Upvotes: 2

Related Questions