1

I add observers in my swift code as follows:

private var keyValueObservations = [NSKeyValueObservation]()

And then in code

  let keyValueObservation = session.observe(\.isRunning, options: .new) { _, change in
          guard let isSessionRunning = change.newValue else { return }

          DispatchQueue.main.async {[weak self] in
            //  self.recordButton.isEnabled = isSessionRunning
            self?.delegate?.cameraSessionStartedRunning(session: self?.session)
          }
      }
      keyValueObservations.append(keyValueObservation)

And then

 private func removeObservers() {
      for keyValueObservation in keyValueObservations {
          keyValueObservation.invalidate()
      }

      keyValueObservations.removeAll()
  }


 deinit {
      removeObservers()
      NSLog("Calling deinit on \(type(of: self))")
  }

Problem is this appears to hold reference count of self as a result of which the object can not be deallocated by setting it to nil. Deinit is never called as a result. How do I fix it?

Deepak Sharma
  • 5,577
  • 7
  • 55
  • 131

1 Answers1

1

The issue here is that you are capturing self earlier than you think. This should fix it:

let keyValueObservation = session.observe(\.isRunning, options: .new) { [weak self] _, change in
    guard let isSessionRunning = change.newValue else { return }

    DispatchQueue.main.async { [weak self] in
        //  self.recordButton.isEnabled = isSessionRunning
        self?.delegate?.cameraSessionStartedRunning(session: self?.session)
    }
}
keyValueObservations.append(keyValueObservation)

So you see it's the closure of the observer function that captures self not when dispatching back onto the main thread.

Upholder Of Truth
  • 4,643
  • 2
  • 13
  • 23