扫描二维码

今天需要做到扫描二维码的功能,一开始想到了用三方,但是看到网上的文章说用原生的更好,所以就使用了苹果原生的进行识别,下面是简单的只是识别二维码,如果需要更复杂的操作可以看我推荐的文章

- (void)sweepCode {
    // 1、获取摄像设备
    AVCaptureDevice *device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
    
    // 2、创建输入流
    AVCaptureDeviceInput *input = [AVCaptureDeviceInput deviceInputWithDevice:device error:nil];
    
    // 3、创建输出流
    AVCaptureMetadataOutput *output = [[AVCaptureMetadataOutput alloc] init];
    
    // 4、设置代理 在主线程里刷新
    [output setMetadataObjectsDelegate:self queue:dispatch_get_main_queue()];
    
    // 5、初始化链接对象(会话对象)
    _session = [[AVCaptureSession alloc] init];
    //高质量采集率
    [_session setSessionPreset:AVCaptureSessionPresetHigh];
    
    // 5.1 添加会话输入
    NSError *error = nil;
    if (input) {
        //设置会话的输入设备
        [_session addInput:input];
    } else {
        NSLog(@"error - %@", [error localizedDescription]);
    }
    
    // 5.2 添加会话输出

    // 设置扫描范围(每一个取值0~1,以屏幕右上角为坐标原点)
    // 注:微信二维码的扫描范围是整个屏幕,这里并没有做处理(可不用设置)
//    output.rectOfInterest = CGRectMake(0.05, 0.05, 0.9, 0.9);
    //CGRectMake(y, x, height, width);
    CGFloat width = SCREENWIDTH;// AVCaptureVideoPreviewLayer的对象的宽度
    CGFloat height = SCREENHEIGHT;// AVCaptureVideoPreviewLayer的对象的高度
    CGFloat extendSpace = 0.f;  //扩展宽出扫描框的长度
    output.rectOfInterest = CGRectMake((self.sweepCase.mr_y - extendSpace)/height, (self.sweepCase.mr_x - extendSpace)/width, (self.sweepCase.mr_height + 2 * extendSpace)/height, (self.sweepCase.mr_width + 2 * extendSpace)/width);
    [_session addOutput:output];
    
    // 6、设置输出数据类型,需要将元数据输出添加到会话后,才能指定元数据类型,否则会报错
    //设置扫描支持的编码格式(如下是设置条形码和二维码兼容)
    output.metadataObjectTypes = @[AVMetadataObjectTypeQRCode, AVMetadataObjectTypeEAN13Code, AVMetadataObjectTypeEAN8Code, AVMetadataObjectTypeCode128Code];
    
    // 7、实例化预览图层, 传递_session是为了告诉图层将来显示什么内容
    _layer = [AVCaptureVideoPreviewLayer layerWithSession:_session];
    _layer.videoGravity = AVLayerVideoGravityResizeAspectFill;
    //设置相机扫描框的大小
    _layer.frame = CGRectMake(0, 0, SCREENWIDTH, SCREENHEIGHT);
    
    // 8、将图层插入当前视图
    [self.view.layer insertSublayer:_layer atIndex:0];
    // 9、启动会话 开始捕获
    [_session startRunning];
}

注意
上面代码需要注意的是,设置扫描的范围。如果需要整个手机屏幕像玻璃一样,能看到手机对面,就不能设置AVCaptureVideoPreviewLayer为扫描框的大小,否则只有扫描框大小里面能透视。
而设置AVCaptureVideoPreviewLayer的frame最好取当前屏幕的宽和高,不能取self.view.frame。不知道为什么,当我取self.view.frame的时候,长宽一直都是600,不准确。
而想只有当二维码在扫描框内才识别的话,设置输出流的rectOfInterest属性,需要注意的是它的取值都是0~1,而且是以屏幕右上角为原点,顺序是CGRectMake(y, x, height, width)。

最后需要在代理AVCaptureMetadataOutputObjectsDelegate方法中做需要做的操作

#pragma mark - AVCaptureMetadataOutputObjectsDelegate
- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputMetadataObjects:(NSArray *)metadataObjects fromConnection:(AVCaptureConnection *)connection {
    NSString *zhQRCode = nil;
    for (AVMetadataObject *metadata in metadataObjects) {
        if ([metadata.type isEqualToString:AVMetadataObjectTypeQRCode]) {  //判别是二维码类型
            zhQRCode = [(AVMetadataMachineReadableCodeObject *)metadata stringValue];
            break;
        }
    }
    NSLog(@"zhQRCode - %@", zhQRCode);
}

其他如果需要复杂一点的操作,可以看下面的文章

参考文章
iOS 二维码扫描(你想要的都在这里了)
iOS原生二维码扫描
iOS开发中用苹果原生API实现扫描二维码功能

推荐阅读更多精彩内容