swift – How can I get data from ObservedObject with onReceive in SwiftUI?


First in your view you need to request the HeadingProvider to start updating heading. You need to listen to objectWillChange notification, the closure has one argument which is the new value that is being set on ObservableObject.

I have changed your Compass a bit:

struct Compass: View {

  @StateObject var headingProvider = HeadingProvider()
  @State private var angle: CGFloat = 0

  var body: some View {
    VStack {
      Image("arrow")
        .resizable()
        .aspectRatio(contentMode: .fit)
        .frame(width: 300, height: 300)
        .modifier(RotationEffect(angle: angle))
        .onReceive(self.headingProvider.objectWillChange) { newHeading in
            withAnimation(.easeInOut(duration: 1.0)) {
                self.angle = newHeading
            }
        }

      Text(String("\(angle)"))
        .font(.system(size: 20))
        .fontWeight(.light)
        .padding(.top, 15)
    }   .onAppear(perform: {
            self.headingProvider.updateHeading()
        })
  }
}

I have written an example HeadingProvider:

public class HeadingProvider: NSObject, ObservableObject {
    
    public let objectWillChange = PassthroughSubject<CGFloat,Never>()
    
    public private(set) var heading: CGFloat = 0 {
        willSet {
            objectWillChange.send(newValue)
        }
    }
    
    private let locationManager: CLLocationManager
    
    public override init(){
        self.locationManager = CLLocationManager()
        super.init()
        self.locationManager.delegate = self
    }
    
    public func updateHeading() {
        locationManager.startUpdatingHeading()
    }
}

extension HeadingProvider: CLLocationManagerDelegate {
    
    public func locationManager(_ manager: CLLocationManager, didUpdateHeading newHeading: CLHeading) {
        DispatchQueue.main.async {
            self.heading = CGFloat(newHeading.trueHeading)
        }
    }
}

Remember you need to handle asking for permission to read user’s location and you need to call stopUpdatingHeading() at some point.

Latest articles

spot_imgspot_img

Related articles

Leave a reply

Please enter your comment!
Please enter your name here

spot_imgspot_img