3

I'm presenting a new view controller (cameraVC) when the camera button is tapped. cameraVC has an AVCaptureSession that takes photos and videos, as well as uses the mic and displays it all on the AVCacptureVideoPreviewLayer. All that works great. But when I dismiss cameraVC using the dismiss() function, I'm not sure how to properly clean up the rest so that cameraVC and its components get completely de-allocated/released. When I tap on the camera button again, the same capture session is still running. In fact, if I started recording a video before I pressed the dismiss button, the camera keeps recording even when the cameraVC is no longer displaying. I would like to completely dismiss cameraVC when the dismiss button is tapped, including stopping and de-allocating that capture session and preview layer.

I've tried, previous to calling dismiss(), session.stopRunning() and self.previewLayer.removeFromSuperLayer(). It works in the sense that they do that, but the actual cameraVC is not de-allocating so when I tap on the camera button again, the functions called from within viewDidLoad() that instantiate the session and preview layer are not once again called. I realize I could call those same functions within viewWillAppear() but wouldn't it be a better practice not to have these things running constantly in the background once the camera button is tapped the first time? Or is it recommended to just have a paused camera session going on in the background once it's been called?

More: When I call dismiss() on cameraVC, viewWillDisappear() is called though deinit() is not. Could someone help explain how to make this work, and/or what the mechanics behind this are? Thanks much.

jcm
  • 41
  • 2

3 Answers3

1

I do three things and deinit is always called.

In my presenter, I have a class level cameraVC, so I set it to nil in viewWillAppear.

In CameraVC I use a CMMotionManager and call stopAccelerometerUpdates on it.

To stop the AVCaptureSession, I call the following method:

func stopCaptureSession() {
  captureSession.stopRunning()

  if let inputs = captureSession.inputs as? [AVCaptureDeviceInput] {
    for input in inputs {
      captureSession.removeInput(input)
    }
  }
}
Don
  • 479
  • 1
  • 4
  • 7
0

I use the AVCaptureSession and AVCaptureVideoPreviewLayer as weak variables.

weak var session: AVCaptureSession!
weak var layer: AVCaptureVideoPreviewLayer!
Display Name
  • 4,502
  • 2
  • 47
  • 63
0

Release AVCaptureSession

Two main points

  • use .stopRunning() function
  • do not create a Retain cycle[About]. For example if you use VNRecognizeTextRequest
let textRequest = VNRecognizeTextRequest(completionHandler: { [weak self] (request, error) in
    guard let self = self else { return }
    self.handleDetectedText(request: request, error: error)
})
yoAlex5
  • 29,217
  • 8
  • 193
  • 205