title: iOS - AVCaptureDevice - Autofocus & Exposure with camera capture
body: <p>I have been implementing Custom Camera using <code>AVCaptureDevice</code>, which require AutoFocus &amp; Exposure to work nicely. I am using the following code to do the camera initialisation </p>
  
  <pre><code>- (void) initializeCamera {
  
      AVAuthorizationStatus status = [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo];
  
      if(status == AVAuthorizationStatusAuthorized) { // authorized
          [self.captureVideoPreviewLayer removeFromSuperlayer];
          self.captureSession = [[AVCaptureSession alloc] init];
          self.captureSession.sessionPreset = AVCaptureSessionPresetPhoto;
          [self removeDeviceObserverForFocus];
          self.captureDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
          [self addDeviceObserverForFocus];
  
          NSError *error = nil;
  
          [self.captureDevice lockForConfiguration:nil]; //you must lock before setting torch mode
          [self.captureDevice setSubjectAreaChangeMonitoringEnabled:YES];
          [self.captureDevice unlockForConfiguration];
  
  
          //Capture layer
          self.captureVideoPreviewLayer = [[AVCaptureVideoPreviewLayer alloc] initWithSession:self.captureSession];
          self.captureVideoPreviewLayer.bounds = CGRectMake(0, 0, CGRectGetWidth([UIScreen mainScreen].bounds), CGRectGetHeight([UIScreen mainScreen].bounds));
          self.captureVideoPreviewLayer.position = CGPointMake(CGRectGetMidX(self.captureVideoPreviewLayer.bounds), CGRectGetMidY(self.captureVideoPreviewLayer.bounds));
          [self.captureVideoPreviewLayer setVideoGravity:AVLayerVideoGravityResizeAspectFill];
          self.captureVideoPreviewLayer.connection.enabled = YES;
          [self.viewCamera.layer insertSublayer:self.captureVideoPreviewLayer atIndex:0];
  
  
          //Capture input
  
          self.captureInput = [AVCaptureDeviceInput deviceInputWithDevice:self.captureDevice error:&amp;error];
          if (!self.captureInput) {
              [self capturePhoto];
          }
          else {
              if ([self.captureSession canAddInput:self.captureInput]) {
                  [self.captureSession addInput:self.captureInput];
              }
          }
  
          self.captureOutput = [[AVCaptureStillImageOutput alloc] init];
          [self.captureOutput setOutputSettings:@{AVVideoCodecKey : AVVideoCodecJPEG}];
          [self.captureSession addOutput:self.captureOutput];
  
          //THIS LINE 
          [self.captureSession setSessionPreset:AVCaptureSessionPresetPhoto];
  
          // setup metadata capture
          AVCaptureMetadataOutput *metadataOutput = [[AVCaptureMetadataOutput alloc] init];
          CGRect visibleMetadataOutputRect = [self.captureVideoPreviewLayer metadataOutputRectOfInterestForRect:self.vwCamera.bounds];
          metadataOutput.rectOfInterest = visibleMetadataOutputRect;
          [self.captureSession addOutput:metadataOutput];
  
          dispatch_async(dispatch_get_main_queue(), ^{
  
              [self.captureSession startRunning];
          });
  
      }
      else if(status == AVAuthorizationStatusNotDetermined){ // not determined
  
          //Try for getting permission
          [AVCaptureDevice requestAccessForMediaType:AVMediaTypeVideo completionHandler:^(BOOL granted) {
              [self performSelectorOnMainThread:@selector(initializeCamera) withObject:nil waitUntilDone:NO];
          }];
      }
  
  }
  
  - (void)removeDeviceObserverForFocus {
      @try {
          while ([self.captureDevice observationInfo] != nil) {
              [self.captureDevice removeObserver:self forKeyPath:@"adjustingFocus"];
          }
      }
      @catch (NSException *exception) {
          NSLog(@"Exception");
      }
      @finally {
      }
  }
  
  - (void)addDeviceObserverForFocus {
      [self.captureDevice addObserver:self forKeyPath:@"adjustingFocus" options:NSKeyValueObservingOptionNew context:nil];
  }
  
  - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
      if( [keyPath isEqualToString:@"adjustingFocus"] ){
          BOOL adjustingFocus = [ [change objectForKey:NSKeyValueChangeNewKey] isEqualToNumber:[NSNumber numberWithInt:1] ];
          if (adjustingFocus) {
              [self showFocusSquareAtPoint:self.viewCamera.center];
          }
      }
  }
  </code></pre>
  
  <p>To monitor focus by movement of camera I am doing the following..</p>
  
  <pre><code>[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(avCaptureDeviceSubjectAreaDidChangeNotification:) name:AVCaptureDeviceSubjectAreaDidChangeNotification object:nil];
  
  #pragma mark - AVCaptureDeviceSubjectAreaDidChangeNotification
  
  -(void)avCaptureDeviceSubjectAreaDidChangeNotification:(NSNotification *)notification{
      CGPoint devicePoint = CGPointMake( 0.5, 0.5 );
  
      [self focusWithMode:AVCaptureFocusModeContinuousAutoFocus exposeWithMode:AVCaptureExposureModeContinuousAutoExposure atDevicePoint:devicePoint monitorSubjectAreaChange:NO];
      [self showFocusSquareAtPoint:self.vwCamera.center];
  
  }
  
  - (void)focusWithMode:(AVCaptureFocusMode)focusMode exposeWithMode:(AVCaptureExposureMode)exposureMode atDevicePoint:(CGPoint)point monitorSubjectAreaChange:(BOOL)monitorSubjectAreaChange
  {
      dispatch_async( dispatch_get_main_queue(), ^{
          AVCaptureDevice *device = self.captureDevice;
          NSError *error = nil;
          if ( [device lockForConfiguration:&amp;error] ) {
              // Setting (focus/exposure)PointOfInterest alone does not initiate a (focus/exposure) operation.
              // Call -set(Focus/Exposure)Mode: to apply the new point of interest.
              if ( device.isFocusPointOfInterestSupported &amp;&amp; [device isFocusModeSupported:focusMode] ) {
                  device.focusPointOfInterest = point;
                  device.focusMode = focusMode;
              }
  
              if ( device.isExposurePointOfInterestSupported &amp;&amp; [device isExposureModeSupported:exposureMode] ) {
                  device.exposurePointOfInterest = point;
                  device.exposureMode = exposureMode;
              }
  
              device.subjectAreaChangeMonitoringEnabled = monitorSubjectAreaChange;
              [device unlockForConfiguration];
          }
          else {
              NSLog( @"Could not lock device for configuration: %@", error );
          }
      } );
  }
  </code></pre>
  
  <p>Everything works as expected when I use this <strong><code>[self.captureSession setSessionPreset:AVCaptureSessionPresetPhoto];</code></strong></p>
  
  <p>If I change the camera preset to something else like <code>AVCaptureSessionPresetHigh</code> AutoFocus and Exposure doesn't work well as expected..</p>
  
  <p>Anyone who has come across such situation?</p>
  
  <p>Thank you for help.</p>