2016-08-20 31 views
7

我的iOS相机应用程序在Objective C中编写时,从锁定屏幕返回时/解锁手机时会冻结其预览图层。AVCapture预览在解锁手机时冻结/卡住

viewWillAppear中调用了所有相机配置设置。到目前为止,我已经取得了成功,除了唯一的问题,即从锁定屏幕返回时,相机预览图层冻结或卡住。我的代码的相机部分如下。

任何帮助,非常感谢。谢谢。 ps:请随时指出我代码中的任何错误,因为我只是一个新手。

- (void)viewWillAppear:(BOOL)animated 
{ 
    [super viewWillAppear:animated]; 
    dispatch_async(dispatch_get_main_queue(), ^{ 
    [self setGUIBasedOnMode]; 
    }); 
} 


-(void) setGUIBasedOnMode 
{ 
if (![self isStreamStarted]) { 
if (shutterActionMode == SnapCamSelectionModeLiveStream) 
{ 
    _flashButton.hidden = true; 
    _cameraButton.hidden = true; 
    _liveSteamSession = [[VCSimpleSession alloc] initWithVideoSize:[[UIScreen mainScreen]bounds].size frameRate:30 bitrate:1000000 useInterfaceOrientation:YES]; 
    [_liveSteamSession.previewView removeFromSuperview]; 
    AVCaptureVideoPreviewLayer *ptr; 
    [_liveSteamSession getCameraPreviewLayer:(&ptr)]; 
    _liveSteamSession.previewView.frame = self.view.bounds; 
    _liveSteamSession.delegate = self; 
} 
else{ 
    [_liveSteamSession.previewView removeFromSuperview]; 
    _liveSteamSession.delegate = nil; 
    _cameraButton.hidden = false; 
    if(flashFlag == 0){ 
     _flashButton.hidden = false; 
    } 
    else if(flashFlag == 1){ 
     _flashButton.hidden = true; 
    } 
    self.session = [[AVCaptureSession alloc] init]; 
    self.previewView.hidden = false; 
    self.previewView.session = self.session; 

    [self configureCameraSettings]; //All The Camera Configuration Settings. 

    dispatch_async(self.sessionQueue, ^{ 
     switch (self.setupResult) 
     { 
      case AVCamSetupResultSuccess: 
      { 
       [self addObservers]; 

       [self.session startRunning]; 

       self.sessionRunning = self.session.isRunning; 
       if(loadingCameraFlag == false){ 
        [self hidingView]; 
       } 
       break; 
      } 
      case AVCamSetupResultCameraNotAuthorized: 
      { 
       dispatch_async(dispatch_get_main_queue(), ^{ 
        NSString *message = NSLocalizedString(@"MyApp doesn't have permission to use the camera, please change privacy settings", @"Alert message when the user has denied access to the camera"); 
        UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"AVCam" message:message preferredStyle:UIAlertControllerStyleAlert]; 
        UIAlertAction *cancelAction = [UIAlertAction actionWithTitle:NSLocalizedString(@"OK", @"Alert OK button") style:UIAlertActionStyleCancel handler:nil]; 
        [alertController addAction:cancelAction]; 

        UIAlertAction *settingsAction = [UIAlertAction actionWithTitle:NSLocalizedString(@"Settings", @"Alert button to open Settings") style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) { 
         [[UIApplication sharedApplication] openURL:[NSURL URLWithString:UIApplicationOpenSettingsURLString]]; 
        }]; 
        [alertController addAction:settingsAction]; 
        [self presentViewController:alertController animated:YES completion:nil]; 
       }); 
       break; 
      } 
      case AVCamSetupResultSessionConfigurationFailed: 
      { 
       dispatch_async(dispatch_get_main_queue(), ^{ 
        NSString *message = NSLocalizedString(@"Unable to capture media", @"Alert message when something goes wrong during capture session configuration"); 
        UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"MyApp" message:message preferredStyle:UIAlertControllerStyleAlert]; 
        UIAlertAction *cancelAction = [UIAlertAction actionWithTitle:NSLocalizedString(@"OK", @"Alert OK button") style:UIAlertActionStyleCancel handler:nil]; 
        [alertController addAction:cancelAction]; 
        [self presentViewController:alertController animated:YES completion:nil]; 
       }); 
       break; 
      } 
     } 
    }); 
} 
} 

-(void)configureCameraSettings 
{ 
self.sessionQueue = dispatch_queue_create("session queue",  DISPATCH_QUEUE_SERIAL); 
self.setupResult = AVCamSetupResultSuccess; 
switch ([AVCaptureDevice  authorizationStatusForMediaType:AVMediaTypeVideo]) 
{ 
    case AVAuthorizationStatusAuthorized: 
    { 
     break; 
    } 
    case AVAuthorizationStatusNotDetermined: 
    { 
     dispatch_suspend(self.sessionQueue); 
     [AVCaptureDevice requestAccessForMediaType:AVMediaTypeVideo completionHandler:^(BOOL granted) { 
      if (! granted) { 
       self.setupResult = AVCamSetupResultCameraNotAuthorized; 
      } 
      dispatch_resume(self.sessionQueue); 
     }]; 
     break; 
    } 
    default: 
    { 
     self.setupResult = AVCamSetupResultCameraNotAuthorized; 
     break; 
    } 
} 

dispatch_async(self.sessionQueue, ^{ 
if (self.setupResult != AVCamSetupResultSuccess) { 
    return; 
} 
self.backgroundRecordingID = UIBackgroundTaskInvalid; 
NSError *error = nil; 

AVCaptureDevice *videoDevice = [IPhoneCameraViewController deviceWithMediaType:AVMediaTypeVideo preferringPosition:AVCaptureDevicePositionBack]; 
AVCaptureDeviceInput *videoDeviceInput = [AVCaptureDeviceInput deviceInputWithDevice:videoDevice error:&error]; 

[self.session beginConfiguration]; 

if ([self.session canAddInput:videoDeviceInput]) { 
    [self.session addInput:videoDeviceInput]; 
    self.videoDeviceInput = videoDeviceInput; 

    dispatch_async(dispatch_get_main_queue(), ^{ 
     UIInterfaceOrientation statusBarOrientation = [UIApplication sharedApplication].statusBarOrientation; 
     AVCaptureVideoOrientation initialVideoOrientation = AVCaptureVideoOrientationPortrait; 
     if (statusBarOrientation != UIInterfaceOrientationUnknown) { 
      initialVideoOrientation = (AVCaptureVideoOrientation)statusBarOrientation; 
     } 
     AVCaptureVideoPreviewLayer *previewLayer = (AVCaptureVideoPreviewLayer *)self.previewView.layer; 
     if (shutterActionMode == SnapCamSelectionModeVideo) 
     { 
      [previewLayer setVideoGravity:AVLayerVideoGravityResizeAspectFill]; 
      if([self.session canSetSessionPreset:AVCaptureSessionPresetMedium]){ 
       [self.session setSessionPreset:AVCaptureSessionPresetMedium]; 
      } 
     } 
     previewLayer.connection.videoOrientation = initialVideoOrientation; 
    }); 
} 
else { 
    self.setupResult = AVCamSetupResultSessionConfigurationFailed; 
} 

AVCaptureDevice *audioDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeAudio]; 
AVCaptureDeviceInput *audioDeviceInput = [AVCaptureDeviceInput deviceInputWithDevice:audioDevice error:&error]; 

if (! audioDeviceInput) { 
} 

if ([self.session canAddInput:audioDeviceInput]) { 
    [self.session addInput:audioDeviceInput]; 
} 
else { 
} 

AVCaptureMovieFileOutput *movieFileOutput = [[AVCaptureMovieFileOutput alloc] init]; 

Float64 TotalSeconds = 10*60; 
int32_t preferredTimeScale = 30; 
CMTime maxDuration = CMTimeMakeWithSeconds(TotalSeconds, preferredTimeScale);   movieFileOutput.maxRecordedDuration = maxDuration; 
movieFileOutput.minFreeDiskSpaceLimit = 1024 * 1024 * 100; 

if ([self.session canAddOutput:movieFileOutput]) { 
    [self.session addOutput:movieFileOutput]; 
    AVCaptureConnection *connection = [movieFileOutput connectionWithMediaType:AVMediaTypeVideo]; 
    if (connection.isVideoStabilizationSupported) { 
     connection.preferredVideoStabilizationMode = AVCaptureVideoStabilizationModeAuto; 
    } 
    self.movieFileOutput = movieFileOutput; 
} 
else { 
    self.setupResult = AVCamSetupResultSessionConfigurationFailed; 
} 

AVCaptureStillImageOutput *stillImageOutput = [[AVCaptureStillImageOutput alloc] init]; 
if ([self.session canAddOutput:stillImageOutput]) { 
    stillImageOutput.outputSettings = @{AVVideoCodecKey : AVVideoCodecJPEG}; 
    [self.session addOutput:stillImageOutput]; 
    self.stillImageOutput = stillImageOutput; 
} 
else { 
    self.setupResult = AVCamSetupResultSessionConfigurationFailed; 
} 
[self.session commitConfiguration]; 
}); 
} 
+0

http://stackoverflow.com/a/30707170/4601170 –

回答

0

ViewDidLoadViewWillAppearViewDidAppear方法应用生命周期的执行之间有很大的区别。 UIViews的

创建或执行一些任务重是原因冻结相当昂贵的,并且你应该避免尽可能多地这样做,在viewWillAppear中方法

看看:

  1. ViewDidLoad:每当我向应该与视图一起出现的视图添加控件时,我就把它放在ViewDidLoad方法中。基本上这个方法在视图加载到内存时被调用。例如,如果我的视图是一个带有3个标签的表单,我会在这里添加标签;如果没有这些形式,视图将永远不会存在
  2. ViewWillAppear:ViewWillAppear通常只是为了更新表单上的数据。因此,对于上面的示例,我将使用它实际将我的域中的数据加载到表单中。创建UIViews相当昂贵,你应该尽可能地避免在ViewWillAppear方法上做这件事,因为当它被调用时,这意味着iPhone已经准备好向用户展示UIView,并且你在这里做的任何事情都很重会以非常明显的方式影响性能(如动画被延迟等)。
  3. ViewDidAppear:ViewDidAppear以启动新线程来执行需要很长时间的事情,例如执行web服务调用以获取上述表单的额外数据。好处是,因为视图已经存在并显示给用户,您可以在获取数据时向用户显示一个很好的“等待”消息。
1

尝试观察UIApplicationDidEnterBackgroundNotification/UIApplicationWillEnterForegroundNotification,UIApplicationWillResignActiveNotification/UIApplicationDidBecomeActiveNotification通知停止/启动捕获会话相应