Sharing a Boolean variable in SwiftUI between views

Hi guys
I have the following problem:
I have MapKit view in swiftui where I'm updating a boolean variable so I know when all the data points are displayed.
I have created the following class and I can "see" the variable changing from false to true and vice versa.
Code Block
class GettingData: ObservableObject {
        
    @Published var doneGettingData : Bool = false
    
        {
        didSet {
            if doneGettingData {
                print("The instance property doneGettingData is now true.")
            } else {
                print("The instance property doneGettingData is now false.")
            }
        }
    }
}

The problem is how to use this variable in ContentView so I can turn on and off a spinner.

I have tried several approaches but nothing works.

In MapView I'm doing it the following way
Code Block
struct MapView: UIViewRepresentable {
    
    let shared = GettingData()
    var startdate : String
    var depth: String
  
    // The makeUIView(context:) method is creates an empty Map View.
       
   func makeUIView(context: Context) -> MKMapView{
         MKMapView(frame: .zero)
          }
    
   func makeCoordinator() -> MapViewCoordinator{
        MapViewCoordinator(self)
    }
    
   func updateUIView(_ uiView: MKMapView, context: Context){
      self.shared.doneGettingData = false
\\\\ rest of the code
uiView.addAnnotations(allLocations)
self.shared.doneGettingData = true
\\\\ rest of the code
                        

The variable does change when I have everything in the map
But how to use it for the spinner ?
Any ideias please ?
Thank you

Replies

One possible way is making GettingData an EnvironmentObject, both for MapView and the view having spinner.
I have tried it but I get a crash when using observableObject
I've run into problems in the past with getting SwiftUI Views to detect changes from ObservableObject classes with Published variables. My solution is to use Combine in the publishing class (your GettingData), creating a specific Publisher, e.g. let statusUpdate = PassthroughSubject<(Bool), Never>(). When doneGettingData changes, e..g. in your didSet, issue a call to statusUpdate.send(doneGettingData)

In your UIView, have .onReceive(shared.statusUpdate, perform: {  doneGettingData in ... do something with doneGettingData status change } You'll probably have to toggle a @State private var to force the View to update.

Don't forget to import Combine.

Also, as an alternative approach, you could try changing let shared in your UIView to @ObservedObject var shared - but I haven’t thought through your code in detail so not sure.

I hope this helps: good luck. Michaela.

PS: The advantage of the Combine method is that if a class makes several data changes, you can do just one send at an appropriate point to get UIView to show all of the changes, rather than the UIView doing updates one by one - which can be annoying to the user.