iOS 【自定義相機 重複閃爍 閃退 解決方案】
阿新 • • 發佈:2019-02-18
最近自己的 WZYCamera 經過多次測試出現了一些問題。
總結以下兩點:
01 在水平放置 iPhone 拍攝的時候不允許豎屏拍攝的 cover 一直閃爍,導致沒有一個合適的 iPhone 擺放姿勢。
02 拍照閃退
分析錯誤成因以及解決辦法:
01 不停閃爍是由於我們 cover 顯示出來的判斷依據是 iPhone 的自身角度以及 iPhone 和水平面夾角,而這個夾角是根據 iPhone 自身的陀螺儀並且通過計算得到的角度。所以說這個角度不是 iPhone 自動返回的,而是經過處理的一個值,這樣一來,多少會有些誤差和計算錯誤。那麼解決辦法就是拿到最原始的資料進行一個判斷。也就是用陀螺儀直接返回的 x、y、z 直接進行判斷。
02 拍照閃退是需要我們在拍照時對錯誤的返回進行一個判定,錯誤的返回我們就不要了。或許是由於光線不好,或許是由於對焦沒完全成功,可能會返回 error,或者丟擲系統方法自定義的異常。我將崩潰異常進行的捕捉和提交,發現錯誤的成因於此:
這個異常出現的原因我總結有這麼幾種:
① 如果你連續拍攝太多(太快)的照片。
② 如果 jpegSampleBuffer 為 NULL 或不是 JPEG 格式,此方法將丟擲 NSInvalidArgumentException。
顯然上圖中的異常是第二種中的 NULL 型別。
具體程式碼修改:
01 解決不停閃爍的 bug。
/** 開啟陀螺儀 */ - (void)startGyroUpdate { if ([self.motionManger isDeviceMotionAvailable]) { //陀螺儀可用 // __weak typeof(self) weakSelf = self; [self.motionManger setDeviceMotionUpdateInterval:0.3]; if (![self.motionManger isDeviceMotionActive]) { [self.motionManger startDeviceMotionUpdatesToQueue:[NSOperationQueue mainQueue] withHandler:^(CMDeviceMotion * _Nullable motion, NSError * _Nullable error) { //1.Gravity 獲取手機的重力值在各個方向上的分量,根據這個就可以獲得手機的空間位置,傾斜角度等 double gravityX = motion.gravity.x; double gravityY = motion.gravity.y; double gravityZ = motion.gravity.z; //2.獲取手機的傾斜角度(zTheta是手機與水平面的夾角, xyTheta是手機繞自身旋轉的角度): // double zTheta = atan2 (gravityZ, sqrtf(gravityX * gravityX + gravityY * gravityY)) / M_PI * 180.0; // double xyTheta = atan2 (gravityX, gravityY) / M_PI * 180.0; // 用 y 值來決定橫豎屏拍攝比角度決定橫豎屏拍攝更加的精確 if (gravityY <= 0.25 && gravityY >= - 0.25) { _alertLabel.hidden = YES; _coverView.hidden = YES; _btn_takePhoto.enabled = YES; } else { _alertLabel.hidden = NO; _coverView.hidden = NO; _btn_takePhoto.enabled = NO; } // NSLog(@"zTheta=%f xyTheta=%f", zTheta, xyTheta); NSLog(@"x --- %.2f,y --- %.2f,z --- %.2f", gravityX, gravityY, gravityZ); }]; } } else { NSLog(@"陀螺儀不可用!"); } }
02 解決拍照崩潰
/** 拍照按鈕方法 */ - (void)takePhoto { AVCaptureConnection *stillImageConnection = [self.stillImageOutput connectionWithMediaType:AVMediaTypeVideo]; if (!stillImageConnection) { NSLog(@"拍照失敗"); // [SVProgressHUD showErrorWithStatus:@"請重新進行拍攝!"]; return; } UIDeviceOrientation curDeviceOrientation = [[UIDevice currentDevice] orientation]; AVCaptureVideoOrientation avcaptureOrientation = [self avOrientationForDeviceOrientation:curDeviceOrientation]; [stillImageConnection setVideoOrientation:avcaptureOrientation]; [stillImageConnection setVideoScaleAndCropFactor:1]; __weak typeof(self) weakSelf = self; [self.stillImageOutput captureStillImageAsynchronouslyFromConnection:stillImageConnection completionHandler:^(CMSampleBufferRef imageDataSampleBuffer, NSError *error) { if (imageDataSampleBuffer == NULL) { NSLog(@"拍照失敗"); // [SVProgressHUD showErrorWithStatus:@"請重新進行拍攝!"]; return; } if (error) { NSLog(@"拍照失敗"); return; } NSData *jpegData = [AVCaptureStillImageOutput jpegStillImageNSDataRepresentation:imageDataSampleBuffer]; UIImage *tempImage = [UIImage imageWithData:jpegData scale:1.0]; UIImage *image = [UIImage imageWithCGImage:tempImage.CGImage scale:1.0 orientation:UIImageOrientationUp]; // 將拍照所得照片返回 if ([weakSelf.delegate respondsToSelector:@selector(cameraViewController:didFinishPickingImage:)]) { [weakSelf.delegate cameraViewController:self didFinishPickingImage:image]; NSLog(@"拍照完成!"); [weakSelf dismissViewControllerAnimated:YES completion:nil]; } }]; }
大家可以進一步下載 WZYCamera 原始碼及 demo 進行下載學習。