美文网首页
AVCaptureStillImageOutput captur

AVCaptureStillImageOutput captur

作者: 天空中的球 | 来源:发表于2021-08-17 16:26 被阅读0次

最近几个版本老出现这个问题:Inconsistent state


Inconsistent state

一、之前处理的方法

  • 1、对于打断的模式进行监听,进行处理
[[NSNotificationCenter defaultCenter] addObserver:self
                                         selector:@selector(sessionWasInterrupted:)
                                             name:AVCaptureSessionWasInterruptedNotification
                                           object:self.session];
[[NSNotificationCenter defaultCenter] addObserver:self
                                         selector:@selector(sessionInterruptionEnded:)
                                             name:AVCaptureSessionInterruptionEndedNotification
                                           object:self.session];
- (void)sessionWasInterrupted:(NSNotification*)notification {
    self.takePhotoView.userActionEnable = NO;
}

- (void)sessionInterruptionEnded:(NSNotification*)notification {
    self.takePhotoView.userActionEnable = YES;
}
  • 2、对于无效的 connection
AVCaptureConnection *connection = [self.imageOutput connectionWithMediaType:AVMediaTypeVideo];
if (!connection || !connection.enabled || !connection.active) {
      return;
}

二、处理的结果

发现如上解决后,没有真正的解决,解决的是另一种情况: Inactive/invalid connection passed Inactive/invalid connection passed

线上时不时还是有这个崩溃发生的

三、再次回归

依然有这个问题,那就只能继续再寻找
突然发现,我们用的是 AVCaptureStillImageOutput

API_DEPRECATED("Use AVCapturePhotoOutput instead.", macos(10.7, 10.15), ios(4.0, 10.0)) API_UNAVAILABLE(tvos) __WATCHOS_PROHIBITED
@interface AVCaptureStillImageOutput : AVCaptureOutput

而且该线上奔溃都是发生在 iOS 11 以上的,所以在没有判断出到底啥错的情况下,猜测是其API 兼容问题,对此采用 AVCapturePhotoOutput

API_AVAILABLE(macos(10.15), ios(10.0), macCatalyst(14.0)) API_UNAVAILABLE(tvos) __WATCHOS_PROHIBITED
@interface AVCapturePhotoOutput : AVCaptureOutput

So, 做了下版本判断的:

/// 拍照动作
- (void)takePhoto {
    if (@available(iOS 11.0, *)) {
        [self takePhotoOutput];
    } else {
        [self takeStillImageOutput];
    }
}

// iOS 11 以上 获取图片
- (void)takePhotoOutput API_AVAILABLE(ios(11.0)) {
    self.takePhotoView.userActionEnable = NO;
    AVCapturePhotoSettings *settings = [AVCapturePhotoSettings photoSettings];
    [self.photoOutput capturePhotoWithSettings:settings delegate:self];
}

// iOS 11 以上 获取图片的回调
- (void)captureOutput:(AVCapturePhotoOutput *)output didFinishProcessingPhoto:(AVCapturePhoto *)photo error:(NSError *)error API_AVAILABLE(ios(11.0)) {
    if (error || !photo) {
        DLog(@"未取到拍摄的图片");
        self.takePhotoView.userActionEnable = YES;
        return;
    }
    CGImageRef cgImage = [photo CGImageRepresentation];
    // 需要调整下方向
    UIImageOrientation imgOrientation = UIImageOrientationRight;
    UIImage *image = [[UIImage alloc] initWithCGImage:cgImage scale:1.0f orientation:imgOrientation];
    [self dealCaptureOutputImage:image];
}

// iOS 10 以下 获取图片
- (void)takeStillImageOutput {
    self.takePhotoView.userActionEnable = NO;
    AVCaptureConnection *connection = [self.stillImageOutput connectionWithMediaType:AVMediaTypeVideo];
    if (!connection || !connection.enabled || !connection.active) {
        DLog(@"拍照失败!");
        self.takePhotoView.userActionEnable = YES;
        return;
    }
        
    if ([connection isVideoStabilizationSupported]) {
        connection.preferredVideoStabilizationMode = AVCaptureVideoStabilizationModeAuto;
    }
    @weakify(self);
    [self.stillImageOutput captureStillImageAsynchronouslyFromConnection:connection completionHandler:^(CMSampleBufferRef  _Nullable imageDataSampleBuffer, NSError * _Nullable error) {
        @strongify(self);
        if (imageDataSampleBuffer == nil) {
            DLog(@"未取到拍摄的图片");
            self.takePhotoView.userActionEnable = YES;
            return;
        }
        //获取拍摄的图片
        NSData *imageData = [AVCaptureStillImageOutput jpegStillImageNSDataRepresentation:imageDataSampleBuffer];
        UIImage *image = [UIImage imageWithData:imageData];
        [self dealCaptureOutputImage:image];
    }];
}

此处直接用 API_AVAILABLE(ios(11.0) 判断,而没有用 iOS 10 是因为 AVCapturePhotoOutput 的回调发现在 iOS 10 到 iOS 11 之间还做了一次处理,于是直接调用了 iOS 11 的

- (void)captureOutput:(AVCapturePhotoOutput *)output didFinishProcessingRawPhotoSampleBuffer:(nullable CMSampleBufferRef)rawSampleBuffer previewPhotoSampleBuffer:(nullable CMSampleBufferRef)previewPhotoSampleBuffer resolvedSettings:(AVCaptureResolvedPhotoSettings *)resolvedSettings bracketSettings:(nullable AVCaptureBracketedStillImageSettings *)bracketSettings error:(nullable NSError *)error 
API_DEPRECATED_WITH_REPLACEMENT("-captureOutput:didFinishProcessingPhoto:error:", ios(10.0, 11.0)) API_UNAVAILABLE(macos) API_UNAVAILABLE(tvos);
- (void)captureOutput:(AVCapturePhotoOutput *)output didFinishProcessingPhoto:(AVCapturePhoto *)photo error:(nullable NSError *)error 
API_AVAILABLE(ios(11.0), macCatalyst(14.0)) API_UNAVAILABLE(tvos);

经过版本判断后,最近一个月暂时木有重现该问题。

这几天刚好 AppStore 有一个 BUG,提交版本后默认成最低支持 iOS 11 的版本。
虽说这个问题今天苹果已经修复,但我个人感觉偶尔来一次,也有好处,强行让用户升级一波了,这样我们就不要去兼容 iOS 9 iOS 10 的用户啦,哈哈哈哈

相关文章

网友评论

      本文标题:AVCaptureStillImageOutput captur

      本文链接:https://www.haomeiwen.com/subject/iuwnsltx.html