ios原生二维码扫描

刚做了一个关于扫二维码的项目,以前没接触过这些,觉得很难,就网上找demo,找到了一个ZBarSDK的第三方框架,别人集成好的,感觉还是挺简单的,后来别人说有原生的而且相对还精确些,也不是很难,就在网上查阅了相关的资料,敲了一个小 demo也挺简单,总结一下的:

1.做原生的二维码扫描需添加其相应的库;


在需要调用扫描的视图导入其头文件#import <AVFoundation/AVFoundation.h>

2.主要用的类有如下几个:

AVCaptureDevice //代表抽象的硬件设备

AVCaptureDeviceInput //代表输入设备

AVCaptureMetadataOutput //表输出数据,管理着输出到一个movie或者图像

AVCaptureSession //它是inputoutput的桥梁。它协调着intputoutput的数据传输

AVCaptureVideoPreviewLayer //供用户扫描可见的层

在 .h文件中声明它

@property (strong, nonatomic) AVCaptureDevice *device;  //代表抽象的硬件设备

@property (strong, nonatomic) AVCaptureDeviceInput *input;  //代表输入设备

@property (strong, nonatomic) AVCaptureMetadataOutput *output;  //表输出数据,管理着输出到一个movie或者图像

@property (strong, nonatomic) AVCaptureSession *session;    //它是input和output的桥梁。它协调着intput到output的数据传输

@property (strong, nonatomic)AVCaptureVideoPreviewLayer *preview;   //供用户扫描可见的层

@property (nonatomic, strong) CALayer *calayer; //扫描线的层

@property (nonatomic, strong) NSTimer *timer;   //定时器

@property (nonatomic, strong)  UIView *boxView; //扫描框

3.实现如下:

a.定义两个成员变量:控制扫描线

    BOOL upOrdown;  //bool判断扫描线上下移动

    NSInteger num;  //位移

b.二维码扫描的核心代码

-(void)initCapture{
    
    // 1. 摄像头设备
    _device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
    
    // 2. 设置输入
    // 因为模拟器是没有摄像头的,因此在此最好做一个判断
    NSError *error;
    _input = [AVCaptureDeviceInput deviceInputWithDevice:self.device error:&error];
    
    if (error) {
        NSLog(@"没有摄像头-%@", error.localizedDescription);
        return;
    }
    
    // 3. 设置输出(Metadata元数据)
    _output = [[AVCaptureMetadataOutput alloc] init];
    
    // 3.1 设置输出的代理
    // 说明:使用主线程队列,相应比较同步,使用其他队列,相应不同步,容易让用户产生不好的体验
    [_output setMetadataObjectsDelegate:self queue:dispatch_get_main_queue()];
    
     // 4. 拍摄会话
    _session = [[AVCaptureSession alloc] init];
    
    [_session setSessionPreset:AVCaptureSessionPresetHigh];
    
     // 添加session的输入和输出
    if ([_session canAddInput:self.input]) {
        
        [_session addInput:self.input];
    }
    
    if ([_session canAddOutput:self.output]) {
        
        [_session addOutput:self.output];
    }
    
    // 4.1 设置输出的格式
    // 提示:一定要先设置会话的输出为output之后,再指定输出的元数据类型!
    _output.metadataObjectTypes = @[AVMetadataObjectTypeQRCode];
    
    // 5. 设置预览图层(用来让用户能够看到扫描情况)
    _preview = [AVCaptureVideoPreviewLayer layerWithSession:_session];
    
    // 5.1 设置preview图层的属性
    _preview.videoGravity = AVLayerVideoGravityResizeAspectFill;
    
    // 5.3 将图层添加到视图的图层
    _preview.frame = self.view.layer.bounds;
    
    [self.view.layer insertSublayer:_preview atIndex:0];
    
    //7.添加扫描框
    _boxView = [[UIView alloc] initWithFrame:CGRectMake((SCREEN_WIDTH-220)/2.0,124,220,220)];
    _boxView.backgroundColor = [UIColor clearColor];
    
    _boxView.layer.borderColor = [UIColor greenColor].CGColor;
    _boxView.layer.borderWidth = 1.0f;
    [self.view addSubview:_boxView];
    
    //8.设置扫描区域
    [_output setRectOfInterest:CGRectMake(124/SCREEN_HEIGHT,((SCREEN_WIDTH-220)/2)/SCREEN_WIDTH,220/SCREEN_HEIGHT,220/SCREEN_WIDTH)];
    
    //9.0 添加扫描框里面的扫描线
    _calayer = [CALayer layer];
    [_calayer setFrame:CGRectMake(0, 10, CGRectGetWidth(_boxView.frame), 1)];
    _calayer.backgroundColor = [UIColor brownColor].CGColor;
    [_boxView.layer addSublayer:_calayer];
    _timer = [NSTimer scheduledTimerWithTimeInterval:0.02 target:self selector:@selector(animationEvent) userInfo:nil repeats:YES];
    
    //9.1设置扫描区域顶部透明图层
    UIView *topView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, SCREEN_WIDTH,_boxView.frame.origin.y)];
    topView.backgroundColor = [UIColor blackColor];
    topView.alpha = 0.4;
    [self.view addSubview:topView];
   //9.2设置扫描区域底部透明图层
    UIView *bottomView = [[UIView alloc] initWithFrame:CGRectMake(0, CGRectGetMaxY(_boxView.frame), SCREEN_WIDTH, SCREEN_HEIGHT-CGRectGetMaxY(_boxView.frame))];
    bottomView.backgroundColor = [UIColor blackColor];
    bottomView.alpha = 0.4;
    [self.view addSubview:bottomView];
    //9.3设置扫描区域左部透明图层
    UIView *leftView = [[UIView alloc] initWithFrame:CGRectMake(0, _boxView.frame.origin.y, _boxView.frame.origin.x, CGRectGetHeight(_boxView.frame))];
    leftView.backgroundColor = [UIColor blackColor];
    leftView.alpha = 0.4;
    [self.view addSubview:leftView];
    
    //9.4设置扫描区域右部透明图层
    UIView *rightView = [[UIView alloc] initWithFrame:CGRectMake(CGRectGetMaxX(_boxView.frame), _boxView.frame.origin.y, SCREEN_WIDTH-CGRectGetMaxX(_boxView.frame),CGRectGetHeight(_boxView.frame))];
    rightView.backgroundColor = [UIColor blackColor];
    rightView.alpha = 0.4;
    [self.view addSubview:rightView];
    
     // 10. 启动会话
    [_session startRunning];
}

c.成功后进入其代理方法

#pragma mark AVCaptureMetadataOutputObjectsDelegate
// 此方法是在识别到QRCode,并且完成转换
// 如果QRCode的内容越大,转换需要的时间就越长
-(void)captureOutput:(AVCaptureOutput *)captureOutput didOutputMetadataObjects:(NSArray *)metadataObjects fromConnection:(AVCaptureConnection *)connection{
    // 会频繁的扫描,调用代理方法
    // 1. 如果扫描完成,停止会话
    NSString *stringValue;
    [_session stopRunning];
    
    if ([metadataObjects count] > 0) {
        AudioServicesPlaySystemSound (1002);    //2.扫描成功后发出声音
        AVMetadataMachineReadableCodeObject *metadataObject = [metadataObjects objectAtIndex:0];
        // 提示:如果需要对url或者名片等信息进行扫描,可以在此进行扩展!
        stringValue = metadataObject.stringValue;
        NSLog(@"infomation is %@",stringValue);
    }
    //销毁定时器
    [_timer invalidate];
    // 4. 删除预览图层
    [self.preview removeFromSuperlayer];
    
}

d.控制扫描线上下扫描代码:

//扫描线上下移动
-(void)animationEvent{
    
    CGFloat height = CGRectGetHeight(_boxView.frame);
    if (upOrdown == NO) {
        num ++;
        _calayer.frame = CGRectMake(0, 10 + num, CGRectGetWidth(_boxView.frame), 1);
        if (num == height) {
            upOrdown = YES;
        }
    }
    else {
        num --;
        _calayer.frame = CGRectMake(0, num - 10, CGRectGetWidth(_boxView.frame), 1);
        if (num == 0) {
            upOrdown = NO;
        }
    }
}








评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值