美文网首页
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