jonye._.jin
jonye._.jin

Reputation: 871

sink() is not called in combine swift

I have LocationManager class that works well. This is part of LocationManager class.

  var headingDegree = PassthroughSubject<Double, Never>()

  func locationManager(_ manager: CLLocationManager, didUpdateHeading newHeading: CLHeading) {
    headingDegree.send(-newHeading.magneticHeading)
  }

headingDegree is the value I want to send to my ViewModel. I debugged it to make sure it has correct values, and it does.

So, in my view model,

class CompassViewViewModel: ObservableObject {
 @Published var degree: Double = 0.0
 @State var cancellable = Set<AnyCancellable>()

 func update() {
    LocationManager.shared.headingDegree.sink {
      self.degree = $0
    }
    .store(in: &cancellable)
  }

I sinked my headingDegree. This is the part that brings my problems. If I put breakpoints in update() function, self.degree = $0 is never called.

This is how my View looks like.

struct CompassView: View {
  @ObservedObject var viewModel: CompassViewViewModel

  init(viewModel: CompassViewViewModel) {
    self.viewModel = viewModel
  }

 var body: some View {
    ZStack {
      Text("aa")
        .font(.footnote)
    }
      .onAppear {
        self.viewModel.update()
    }
  }
}

Could you tell me why my sink() is not called?

Upvotes: 4

Views: 3879

Answers (3)

possen
possen

Reputation: 9266

Another manifestation of this is if you make the scope of the var cancellable = Set<AnyCancellable>() function scope rather than instance scope. It frees it before the async code in the callbacks are called. Putting it in the instance keeps it alive long enough for calls to complete.

struct MyClass {
    var cancellable = Set<AnyCancellable>() // here

    func action() {
        // var cancellable = Set<AnyCancellable>() // Not here
        resourceLoader()
            .sink { completion in
            } receiveValue: { response in
               print(response)
            }
            .store(in: &cancellable)
     }
 }

Upvotes: 0

Mostfa Essam
Mostfa Essam

Reputation: 927

Update

in swiftUI1, viewDidLoad in UIHostingcontroller isn't called.


when using combine, with UIKit, subscribing (Sink) in viewDidload, didn't work, instead, subscribe in viewDidAppear

Upvotes: 1

jonye._.jin
jonye._.jin

Reputation: 871

I changed @State var cancellable = Set<AnyCancellable>() to private var cancellable = Set<AnyCancellable>() and it works well.

Upvotes: 3

Related Questions