iOS二维码扫描

公司最近要添加一个二维码扫描网页登录的功能,所以最近研究了一下iOS关于二维码扫描的功能
因为移动端不涉及二维码的生成,所以只做关于二维码的扫描(这里感谢一下SGQRCode的作者)

我们先来说说AVCaptureSession。AVCaptureSession是AVFoundation框架的核心类,用于捕捉视频和音频,协调视频和音频的输入和输出流.下面是围绕AVCaptureSession的图
iOS二维码扫描_第1张图片
5301663-fab2e80855a3ef4b.jpg

摄像头扫描二维码

用摄像头扫描二维码就需要我们刚才说的AVCaptureSession,具体怎么实现,我们来看demo。

框架

首先导入我们要用到的框架,因为扫描和识别都是在系统AVFoundation下的做的,所以第一步就要把框架主头文件导入 #import

头文件

/** 回话对象属性*/
@property (nonatomic, strong) AVCaptureSession *session;

/** 摄像头预览图层*/
@property (nonatomic, strong) AVCaptureVideoPreviewLayer *previewLayer;

实现部分

    // 创建回话对象
    self.session = [[AVCaptureSession alloc] init];
    
    // 设置回话对象图像采集率
    [self.session setSessionPreset:AVCaptureSessionPresetHigh];
    
    // 获取摄像头设备
    AVCaptureDevice *device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
    
    // 创建回话输入对象
    NSError *inputError = nil;
    AVCaptureDeviceInput *input = [AVCaptureDeviceInput deviceInputWithDevice:device error:&inputError];
    
    // 添加会话输入
    [self.session addInput:input];
    
    // 创建输出对象
    AVCaptureMetadataOutput *output = [[AVCaptureMetadataOutput alloc] init];
    
    // 设置输出对象代理
    [output setMetadataObjectsDelegate:self queue:dispatch_get_main_queue()];
    
    // 添加会话输出
    [self.session addOutput:output];
    
    // 设置输出数据类型,需要将元数据输出添加到回话后,才能制定元数据,否则会报错
    // 二维码和条形码可以一起设置
    output.metadataObjectTypes = @[AVMetadataObjectTypeQRCode, AVMetadataObjectTypeEAN13Code,  AVMetadataObjectTypeEAN8Code, AVMetadataObjectTypeCode128Code];
    
    // 创建摄像头预览图层
    self.previewLayer = [AVCaptureVideoPreviewLayer layerWithSession:self.session];
    
    self.previewLayer.videoGravity = AVLayerVideoGravityResizeAspectFill;
    
    self.previewLayer.frame = self.view.frame;
    
    // 将图层插入当前图层
    [self.view.layer insertSublayer:self.previewLayer atIndex:0];
    
    // 启动会话
    [self.session startRunning];

主体方法实现了以后,我们来看一下AVCaptureMetadataOutputObjectsDelegate方法- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputMetadataObjects:(NSArray *)metadataObjects fromConnection:(AVCaptureConnection *)connection;,当二维码扫描成功之后,系统将自动调用这个代理方法。

AVCaptureMetadataOutputObjectsDelegate

- (void)captureOutput:(AVCaptureOutput *)output didOutputMetadataObjects:(NSArray<__kindof AVMetadataObject *> *)metadataObjects fromConnection:(AVCaptureConnection *)connection {
    
    // 1、如果扫描完成,停止会话
    [self.session stopRunning];
    
    // 2、删除预览图层
    [self.previewLayer removeFromSuperlayer];
    
    // 3、设置界面显示扫描结果
    if (metadataObjects && metadataObjects.count > 0) {
        // 播放音效
        NSString *audioFile = [[NSBundle mainBundle] pathForResource:@"sound" ofType:@"wav"];
        NSURL *fileUrl = [NSURL fileURLWithPath:audioFile];
        
        SystemSoundID soundID = 0;
        AudioServicesCreateSystemSoundID((__bridge CFURLRef)(fileUrl), &soundID);
        AudioServicesAddSystemSoundCompletion(soundID, NULL, NULL, soundCompleteCallback, NULL);
        AudioServicesPlaySystemSound(soundID); // 播放音效
        AVMetadataMachineReadableCodeObject *obj = metadataObjects.firstObject;
        // 取出二维码扫描到的内容
        NSLog(@"二维码内容:::%@",obj.stringValue);
    }
}
// 播放音效成功回调
void soundCompleteCallback (){
   
}

如果想监听设备摄像头实时的视频流就将会话输出对象添加AVCaptureVideoDataOutputSampleBufferDelegate代理监听实现- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection;代理方法

AVCaptureVideoDataOutputSampleBufferDelegate

[output setSampleBufferDelegate:self queue:dispatch_get_main_queue()];

实现方法

- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection {
    // 这个方法会时时调用,但内存很稳定
    CFDictionaryRef metadataDict = CMCopyDictionaryOfAttachments(NULL,sampleBuffer, kCMAttachmentMode_ShouldPropagate);
    NSDictionary *metadata = [[NSMutableDictionary alloc] initWithDictionary:(__bridge NSDictionary*)metadataDict];
    CFRelease(metadataDict);
    NSDictionary *exifMetadata = [[metadata objectForKey:(NSString *)kCGImagePropertyExifDictionary] mutableCopy];
    float brightnessValue = [[exifMetadata objectForKey:(NSString *)kCGImagePropertyExifBrightnessValue] floatValue];
    
    NSLog(@"%f",brightnessValue);
}

你可能感兴趣的:(iOS二维码扫描)