美文网首页
iOS二维码扫描

iOS二维码扫描

作者: QL_fish | 来源:发表于2017-12-01 13:59 被阅读133次

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

    我们先来说说AVCaptureSession。AVCaptureSession是AVFoundation框架的核心类,用于捕捉视频和音频,协调视频和音频的输入和输出流.下面是围绕AVCaptureSession的图 5301663-fab2e80855a3ef4b.jpg

    摄像头扫描二维码

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

    框架

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

    头文件

    /** 回话对象属性*/
    @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二维码扫描

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