iOS 原生扫码二维码与自定义相机

2018-07-23  本文已影响0人  牛程程

实现扫码二维码与自定义相机的功能,都要用到 AVFoundation 框架。
完成功能后发现,这俩个功能在实现上大致相同,唯一不同的地方是 设置 AVCaptureSession 的 output。

扫描二维码

 self.metadataOutput = [AVCaptureMetadataOutput new];
  //输出的类 为 AVCaptureMetadataOutput
    [self.session addOutput:self.metadataOutput];
    self.metadataOutput.metadataObjectTypes = @[
                                                AVMetadataObjectTypeQRCode,
                                                ];
    [self.metadataOutput setMetadataObjectsDelegate:self queue:dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)];

//可以通过设置 rectOfInterest 属性,来调整扫码区域。

自定义相机

    self.photoOutput = [[AVCapturePhotoOutput alloc] init];
  //输出的类 为 AVCapturePhotoOutput
    NSDictionary *setDic = @{
                             AVVideoCodecKey:AVVideoCodecTypeJPEG,
                             };
    self.photoSettings = [AVCapturePhotoSettings photoSettingsWithFormat:setDic];
    [self.photoOutput setPhotoSettingsForSceneMonitoring:self.photoSettings];
    [self.session addOutput:self.photoOutput];

//可以通过设置 rectOfInterest 属性,来调整扫码区域。

具体实现如下:

首先,添加如下属性

@interface XXXCaptureViewController ()<AVCaptureMetadataOutputObjectsDelegate,AVCapturePhotoCaptureDelegate>

@property (nonatomic, assign)BOOL currentAuthStatus;

@property (nonatomic, strong)AVCaptureDevice *device;
@property (nonatomic, strong)AVCaptureSession *session;
@property (nonatomic, strong)AVCaptureDeviceInput *input;
@property (nonatomic, strong)AVCaptureMetadataOutput *metadataOutput;
@property (nonatomic, strong)AVCapturePhotoOutput *photoOutput;
@property (nonatomic, strong)AVCapturePhotoSettings *photoSettings;

@property (nonatomic, strong)UIButton *takephotoButton;

在使用相机前,要查看是否授权

- (BOOL)authStatus
{
    AVAuthorizationStatus authStatus = [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo];
    
    if (authStatus == AVAuthorizationStatusAuthorized)
    {
        return YES;
    }
    else
    {
        return NO;
    }
}

如果该 App 没有授权相机功能,需要请求授权

__block typeof(self) weakSelf = self;
    [AVCaptureDevice requestAccessForMediaType:AVMediaTypeVideo completionHandler:^(BOOL granted) {
        
        if (granted == NO)
        {
            weakSelf.currentAuthStatus = NO;
        }
        else
        {
            weakSelf.currentAuthStatus = YES;
            
            [weakSelf configureCaptureSessionSettting];
        }

然后添加属性的相关设置

- (void)configureCaptureSessionSettting
{
    if (self.currentAuthStatus == NO)
    {
        return;
    }
    
    self.session = [AVCaptureSession new];
    self.device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
    NSError *error;
    self.input = [AVCaptureDeviceInput  deviceInputWithDevice:self.device error:&error];
    
    [self.session addInput:self.input];
    
//扫二维码
//    [self.session addOutput:self.metadataOutput];
//    self.metadataOutput.metadataObjectTypes = @[
//                                                AVMetadataObjectTypeQRCode,//可以添加 AVMetadataObjectTypeCode39Code 等类型同时扫描条形码
//                                                ];
//    [self.metadataOutput setMetadataObjectsDelegate:self queue:dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)];
    
  //捕获照片
    self.photoOutput = [[AVCapturePhotoOutput alloc] init];
    NSDictionary *setDic = @{
                             AVVideoCodecKey:AVVideoCodecTypeJPEG,
                             };
    self.photoSettings = [AVCapturePhotoSettings photoSettingsWithFormat:setDic];
    [self.photoOutput setPhotoSettingsForSceneMonitoring:self.photoSettings];
    [self.session addOutput:self.photoOutput];
    
    
    AVCaptureVideoPreviewLayer* previewLayer = [AVCaptureVideoPreviewLayer layerWithSession:self.session];
    previewLayer.videoGravity = AVLayerVideoGravityResizeAspectFill;
    
    dispatch_async(dispatch_get_main_queue(), ^{
        
        [previewLayer setFrame:self.view.bounds];
        [self.view.layer insertSublayer:previewLayer atIndex:0];
    });
   
    
}

最后一步啦,开始捕获数据和停止补货。最好不要把它们放在主线程中使用。因为 startRunning 和 stopRunning 其实是一个 block,主线程调用可能会引起,UI卡顿。苹果官方具体解释:https://developer.apple.com/documentation/avfoundation/avcapturesession

- (void)viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:animated];
    
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{

        [self.session startRunning];
    });

}
- (void)viewWillDisappear:(BOOL)animated
{
    [super viewWillDisappear:animated];
    
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        
        [self.session stopRunning];
    });
}
上一篇下一篇

猜你喜欢

热点阅读