二维码扫描

一.原生二维码扫描

AVCaptureSession

管理输入(AVCaptureInput)和输出(AVCaptureOutput)流,包含开启和停止会话方法。

AVCaptureDeviceInput

是AVCaptureInput的子类,可以作为输入捕获会话,用AVCaptureDevice实例初始化。

AVCaptureDevice

代表了物理捕获设备如:摄像机。用于配置等底层硬件设置相机的自动对焦模式。

AVCaptureMetadataOutput

是AVCaptureOutput的子类,处理输出捕获会话。捕获的对象传递给一个委托实现AVCaptureMetadataOutputObjectsDelegate协议。协议方法在指定的派发队列(dispatch queue)上执行。

AVCaptureVideoPreviewLayer

CALayer的一个子类,显示捕获到的相机输出流。

1.遵守协议

引入 :

  #import 

2.声明属性

 {
     AVCaptureSession * session;//输入输出的中间桥梁
 }

3.在viewdidload中加入下面的方法

 //获取摄像设备
AVCaptureDevice * device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
//创建输入流
AVCaptureDeviceInput * input = [AVCaptureDeviceInput deviceInputWithDevice:device error:nil];
//创建输出流
AVCaptureMetadataOutput * output = [[AVCaptureMetadataOutput alloc]init];
//设置代理 在主线程里刷新
[output setMetadataObjectsDelegate:self queue:dispatch_get_main_queue()];

//初始化链接对象
session = [[AVCaptureSession alloc]init];
//高质量采集率
[session setSessionPreset:AVCaptureSessionPresetHigh];

[session addInput:input];
[session addOutput:output];
//设置扫码支持的编码格式(如下设置条形码和二维码兼容)
output.metadataObjectTypes=@[AVMetadataObjectTypeQRCode,AVMetadataObjectTypeEAN13Code, AVMetadataObjectTypeEAN8Code, AVMetadataObjectTypeCode128Code];

AVCaptureVideoPreviewLayer * layer = [AVCaptureVideoPreviewLayer layerWithSession:session];
layer.videoGravity=AVLayerVideoGravityResizeAspectFill;
layer.frame=self.view.layer.bounds;
[self.view.layer insertSublayer:layer atIndex:0];
//开始捕获
[session startRunning];

实现完成二维码条形码的扫描

-(void)captureOutput:(AVCaptureOutput *)captureOutput didOutputMetadataObjects:(NSArray *)metadataObjects fromConnection:  (AVCaptureConnection *)connection{
if (metadataObjects.count>0) {
    //[session stopRunning];
    AVMetadataMachineReadableCodeObject * metadataObject = [metadataObjects objectAtIndex : 0 ];
    //输出扫描字符串
    NSLog(@"%@",metadataObject.stringValue);
    }
}

三.从相册选择二维码进行扫描

UIImagePickerController *picker = [[UIImagePickerController alloc] init];
picker.delegate = self;
picker.allowsEditing = true;
[self presentViewController:picker animated:true completion:nil];

遵守代理

UINavigationControllerDelegate, UIImagePickerControllerDelegate

执行代理方法

pragma mark - UIImagePickerControllerDelegate

  • (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info {

    [picker dismissViewControllerAnimated:true completion:^{
    UIImage *image = info[UIImagePickerControllerEditedImage];
    if (!image) {
    image = info[UIImagePickerControllerOriginalImage];
    }
    NSData *imageData = UIImageJPEGRepresentation(image, 1);
    // kCIContextUseSoftwareRenderer : 软件渲染 -- 可以消除 "BSXPCMessage received error for message: Connection interrupted" 警告
    // kCIContextPriorityRequestLow : 低优先级在 GPU 渲染-- 设置为false可以加快图片处理速度
    CIContext *context = [CIContext contextWithOptions:@{kCIContextUseSoftwareRenderer : @(true), kCIContextPriorityRequestLow : @(false)}];

      CIDetector *detector = [CIDetector detectorOfType:CIDetectorTypeQRCode context:context options:nil];
      CIImage *ciImage = [CIImage imageWithData:imageData];
      
      NSArray *ar = [detector featuresInImage:ciImage];
      CIQRCodeFeature *feature = [ar firstObject];
      NSLog(@"detector: %@", detector);
      NSLog(@"context: %@", feature.messageString);
      UIAlertController *alert = [UIAlertController alertControllerWithTitle:nil message:[NSString stringWithFormat:@"扫描结果:%@", feature.messageString ?: @"空"] preferredStyle:UIAlertControllerStyleAlert];
      [alert addAction:[UIAlertAction actionWithTitle:@"Sure" style:UIAlertActionStyleCancel handler:nil]];
      [self presentViewController:alert animated:true completion:nil];
      
      }];
    }
    
       - (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker     {
      [picker dismissViewControllerAnimated:true completion:nil];
     }
    

经过测试CIDetector 这个方法必须在5s以上的设备才可以使用

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