title: How do I properly cleanup an AVCaptureSession and AVCaptureVideoPreviewLayer
body: <p>I'm using the AVFoundation api to create a camera preview view and I'm having trouble cleaning up after I'm done.</p>
  
  <p>The best answer I've found to this problem is in this <a href="https://stackoverflow.com/questions/3741121/how-to-properly-release-an-avcapturesession/3858077#3858077">SO thread</a>, thanks Codo. </p>
  
  <p>However, he doesn't address the deallocation of the AVCaptureVideoPreviewLayer, and that's where I'm having trouble. </p>
  
  <p>In my view controller class I have some initialization code in a startCameraCapture method. Listening to Codo's answer, I'm using <code>dispatch_set_finalizer_f(_captureQueue, capture_cleanup);</code> to register a callback to be called when the queue is truly closed.
  I'm also retaining self, to make sure my object doesn't go away before the queue is done calling my object. I then use the capture_cleanup callback to release self. </p>
  
  <pre><code>-(void) startCameraCapture {
      _camSession = [[AVCaptureSession alloc] init];
      if (_previewLayer == nil) {
          _previewLayer = [AVCaptureVideoPreviewLayer layerWithSession:_camSession];
      }
      _previewLayer.frame = self.compView.bgView.frame;   
      [self.compView.bgView.layer addSublayer:_previewLayer];
  
      // Get the default camera device
      AVCaptureDevice* camera = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
  
      // Create a AVCaptureInput with the camera device
      NSError *error=nil;
      AVCaptureInput* cameraInput = [[AVCaptureDeviceInput alloc] initWithDevice:camera error:&amp;error];
      if (cameraInput == nil) {
          NSLog(@"Error to create camera capture:%@",error);
  
      }
  
      AVCaptureVideoDataOutput* videoOutput = [[[AVCaptureVideoDataOutput alloc] init] autorelease];
  
      // create a queue to run the capture on
      _captureQueue=dispatch_queue_create("captureQueue", NULL);
      dispatch_set_context(_captureQueue, self);
      dispatch_set_finalizer_f(_captureQueue, capture_cleanup);
  
      // setup our delegate
      [videoOutput setSampleBufferDelegate:self queue:_captureQueue];
  
      dispatch_release(_captureQueue);
  
      // retain self as a workouround a queue finalization bug in apples's sdk 
      // per Stackoverflow answer https://stackoverflow.com/questions/3741121/how-to-properly-release-an-avcapturesession
      [self retain];
  
      // configure the pixel format
      videoOutput.videoSettings = [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithUnsignedInt:kCVPixelFormatType_32BGRA], (id)kCVPixelBufferPixelFormatTypeKey,
                                   nil];
  
      // and the size of the frames we want
      [_camSession setSessionPreset:AVCaptureSessionPresetMedium];
  
      // Add the input and output
      [_camSession addInput:cameraInput];
      [_camSession addOutput:videoOutput];
  
      [cameraInput release];
  
      // Start the session
      [_camSession startRunning];     
  }
  </code></pre>
  
  <p>Here the capture_cleanup callback:</p>
  
  <pre><code> static void capture_cleanup(void* p)
      {
          LiveCompViewController* ar = (LiveCompViewController*)p;
          [ar release];  // releases capture session if dealloc is called
      }
  </code></pre>
  
  <p>Then my cleanup code looks like this: </p>
  
  <pre><code>-(void) stopCameraCapture {
  [_camSession stopRunning];
      [_camSession release];
      _camSession=nil;    
  
      // Remove the layer in order to release the camSession
      [_previewLayer removeFromSuperlayer];
      _previewLayer = nil;
  
  }
  </code></pre>
  
  <p>The problem I'm having is that removing the _previewLayer from the superlayer in stopCameraCapture is causing the following console error:</p>
  
  <blockquote>
    <p>"...modifying layer that is being finalized..."</p>
  </blockquote>
  
  <p>But I need to remove the layer so that it gets released and deallocated so that it releases the _camSession which in turn releases the dispatch_queue and then finally calls my capture_cleanup callback which finally releases self.</p>
  
  <p>I don't understand why I'm getting the console error and how to fix it. Why is the Layer being finalized at the time I'm calling <code>[_previewLayer removeFromSuperlayer]</code> if self.dealloc hasn't been called. </p>
  
  <p>Note: self is a viewController and I haven't popped it yet, so it is retained by the NavigationContoller.</p>