iOS自带扫码实现以及扫码类型

时间:2024-03-01 07:10:27
  1 //
  2 //  SYTCodeScanerViewController.m
  3 //  SYTCodeScan
  4 //
  5 //  Created by iMac on 15/5/6.
  6 //  Copyright (c) 2015年 S.F. All rights reserved.
  7 //
  8 
  9 #import "SYTCodeScanerViewController.h"
 10 #import <AVFoundation/AVFoundation.h>
 11 
 12 @interface SYTCodeScanerViewController ()<AVCaptureMetadataOutputObjectsDelegate, UIImagePickerControllerDelegate, UINavigationControllerDelegate>
 13 
 14 @property (nonatomic ,strong) AVCaptureSession *captureSession;                 //捕捉会话
 15 @property (nonatomic, strong) AVCaptureVideoPreviewLayer *videoPreviewLayer;    //预览图层layer
 16 @property (strong, nonatomic) UIView *boxView;                                  //扫描识别框
 17 
 18 @property (weak, nonatomic) IBOutlet UILabel *resoultLab;                       //结果显示Lab
 19 
 20 @property (weak, nonatomic) IBOutlet UIButton *scanImageButton;
 21 
 22 @property (nonatomic, strong) UIImagePickerController *imagePickerController;
 23 
 24 @end
 25 
 26 @implementation SYTCodeScanerViewController
 27 
 28 - (void)viewDidLoad {
 29     [super viewDidLoad];
 30     
 31     _captureSession = nil;
 32     
 33     [self startScan];
 34     
 35 }
 36 
 37 - (void)startScan
 38 {
 39     //初始化设备(摄像头)
 40     NSError *error = nil;
 41     AVCaptureDevice *captureDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
 42     
 43     //创建输入流
 44     AVCaptureDeviceInput *input = [AVCaptureDeviceInput deviceInputWithDevice:captureDevice error:&error];
 45     if (error)
 46     {
 47         NSLog(@"没有摄像头:%@", error.localizedDescription);
 48         return;
 49     }
 50     
 51     
 52     //创建输出流
 53     AVCaptureMetadataOutput *output = [[AVCaptureMetadataOutput alloc] init];
 54     
 55     //实例化捕捉会话并添加输入,输出流
 56     _captureSession = [[AVCaptureSession alloc] init];
 57     //高质量采集率
 58     [_captureSession setSessionPreset:AVCaptureSessionPresetHigh];
 59     
 60     [_captureSession addInput:input];
 61     [_captureSession addOutput:output];
 62     
 63     //设置输出的代理,在主线程里刷新
 64     [output setMetadataObjectsDelegate:self queue:dispatch_get_main_queue()];   //用串行队列新线程结果在UI上显示较慢
 65     
 66     //扫码类型
 67     [output setMetadataObjectTypes:@[AVMetadataObjectTypeQRCode,         //二维码
 68                                      AVMetadataObjectTypeCode39Code,     //条形码   韵达和申通
 69                                      AVMetadataObjectTypeCode128Code,    //商品条码  顺丰用的
 70                                      AVMetadataObjectTypeCode39Mod43Code,
 71                                      AVMetadataObjectTypeEAN13Code,
 72                                      AVMetadataObjectTypeEAN8Code,
 73                                      AVMetadataObjectTypeCode93Code, //条形码,星号来表示起始符及终止符,如邮政EMS单上的条码
 74                                      AVMetadataObjectTypeUPCECode]];
 75     
 76     _videoPreviewLayer = [[AVCaptureVideoPreviewLayer alloc] initWithSession:_captureSession];
 77     
 78     [_videoPreviewLayer setVideoGravity:AVLayerVideoGravityResizeAspectFill];
 79     
 80     //添加预览图层
 81     _videoPreviewLayer.frame = self.view.frame;
 82     [self.view.layer addSublayer:_videoPreviewLayer];
 83     [self.view bringSubviewToFront:self.view.subviews[0]];
 84 
 85     
 86     //扫描框
 87     
 88     _boxView = [[UIView alloc] initWithFrame:CGRectMake(60, 100, 200, 200)];
 89     _boxView.layer.borderColor = [UIColor greenColor].CGColor;
 90     _boxView.layer.borderWidth = 1.0f;
 91     [self.view addSubview:_boxView];
 92     
 93     //扫描识别范围
 94     output.rectOfInterest = CGRectMake(100 / self.view.bounds.size.height,
 95                                        60  / self.view.bounds.size.width,
 96                                        200 / self.view.bounds.size.height,
 97                                        200 / self.view.bounds.size.width);
 98     
 99     //开始扫描
100     [_captureSession startRunning];
101     
102     
103 }
104 
105 #pragma mark - 扫描结果代理方法
106 - (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputMetadataObjects:(NSArray *)metadataObjects fromConnection:(AVCaptureConnection *)connection
107 {
108     [_captureSession stopRunning];
109 //    [_videoPreviewLayer removeFromSuperlayer];
110     
111     if (metadataObjects.count > 0) {
112         
113         AVMetadataMachineReadableCodeObject *obj = metadataObjects[0];
114         
115         _resoultLab.text = obj.stringValue;
116         
117         NSLog(@"扫码扫描结果,obj.stringValue == %@", obj.stringValue);
118     }
119     
120 }
121 
122 
123 #pragma mark 选择照片
124 
125 #pragma -mark - UIImagePickerViewControllerDelegate
126 - (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
127 {
128     
129     NSLog(@"info == %@", info);
130     [self.imagePickerController dismissViewControllerAnimated:YES completion:nil];
131     
132     UIImage *image = [info objectForKey:@"UIImagePickerControllerOriginalImage"];
133     
134     
135 }
136 
137 
138 - (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker
139 {
140     [self.imagePickerController dismissViewControllerAnimated:YES completion:nil];
141 
142 }
143 
144 - (IBAction)photoPickBtn:(UIButton *)sender {
145     
146     if (!_imagePickerController) {
147         
148         _imagePickerController = [[UIImagePickerController alloc] init];
149         _imagePickerController.delegate =self;
150         _imagePickerController.SourceType = UIImagePickerControllerSourceTypePhotoLibrary;
151     }
152     
153     [self presentViewController:self.imagePickerController animated:YES completion:nil];
154 }
155 @end

 

首先,AVCaptureMetadataOutput类中有一个这样的属性(在IOS7.0之后可用):

@property(nonatomic) CGRect rectOfInterest;

  这个属性大致意思就是告诉系统它需要注意的区域,大部分APP的扫码UI中都会有一个框,提醒你将条形码放入那个区域,这个属性的作用就在这里,它可以设置一个范围,只处理在这个范围内捕获到的图像的信息。如此一来,可想而知,我们代码的效率又会得到很大的提高,在使用这个属性的时候。需要几点注意:

1、这个CGRect参数和普通的Rect范围不太一样,它的四个值的范围都是0-1,表示比例。

2、经过测试发现,这个参数里面的x对应的恰恰是距离左上角的垂直距离,y对应的是距离左上角的水平距离。

3、宽度和高度设置的情况也是类似。

3、举个例子如果我们想让扫描的处理区域是屏幕的下半部分,我们这样设置

output.rectOfInterest=CGRectMake(0.5,0,0.5, 1);