iOS开发------原生的二维码

iOS7之前,开发者进行扫码编程时,一般会借助第三方库。扫描二维码 OC 的开源库有 ZBar和ZXing,iOS7之后,系统的AVMetadataObject类中,为我们提供了解析二维码的接口。经过测试,使用原生API扫描和处理的效率非常高,远远高于第三方库。

二维码扫描

在开始之前最重要的一步是要先导入原生的音视频框架即 AVFoundation.framework 。

首先在 #import "QRView.h" 中

@class QRView ;

@protocol QRViewDelegate <NSObject>

/// 代理回调扫描结果
// View 扫一扫视图
// result 扫一扫结果

- (void)qrView:(QRView *)View ScanResult:(NSString *)result;


@end
@interface QRView : UIView

// 声明一个代理
@property (nonatomic, assign) id<QRViewDelegate>delegate;

@property (nonatomic, assign,readonly) CGRect scanViewFrame;

// 开始扫描的方法
- (void)startScan;

// 结束扫描
- (void)stopScan;


@end

接下来在  #import "QRView.m" 中

#import "QRView.h"
#import <AVFoundation/AVFoundation.h>

// 遵守代理

@interface QRView ()<AVCaptureMetadataOutputObjectsDelegate>


@end

@implementation QRView
{
    AVCaptureSession *_session;
    UIImageView *_scanView;
    UIImageView *_lineView;
}

- (instancetype)initWithFrame:(CGRect)frame{
    self = [super initWithFrame:frame];
    if (self) {
        [self initView];
    }
    return self;
}

- (void)initView
{
    UIImage *scanImage = [UIImage imageNamed:@"scanscanBg"];
    CGFloat width = CGRectGetWidth(self.frame);
    CGFloat height = CGRectGetHeight(self.frame);
    
    CGFloat scanW = 200;
    CGRect scanFrame = CGRectMake(width/2.-100, height/2.-100, scanW, scanW);
    _scanViewFrame = scanFrame;
    
    
    _scanView = [[UIImageView alloc]initWithImage:scanImage];
    _scanView.backgroundColor = [UIColor clearColor];
    _scanView.frame = scanFrame;
    [self addSubview:_scanView];
    
    
    //获取摄像设备
    AVCaptureDevice *device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
    
    //闪光灯
    if ([device hasFlash] && [device hasTorch]) {
        [device lockForConfiguration:nil];
        [device setFlashMode:AVCaptureFlashModeAuto];
        [device setTorchMode:AVCaptureTorchModeAuto];
        [device unlockForConfiguration];
    }
    //创建输入流
    AVCaptureDeviceInput *input = [AVCaptureDeviceInput deviceInputWithDevice:device error:nil];
    
    //创建输出流
    AVCaptureMetadataOutput *output = [[AVCaptureMetadataOutput alloc]init];
    //设置代理 刷新线程
    [output setMetadataObjectsDelegate:self queue:dispatch_get_main_queue()];
    
    output.rectOfInterest = [self rectOfInterestByScanViewRect:_scanView.frame];
    //初始化连接对象
    _session = [[AVCaptureSession alloc]init];
    
    //采集率
    _session.sessionPreset = AVCaptureSessionPresetHigh;
    
    if (input) {
        [_session addInput:input];
    }
    
    if (output) {
        [_session addOutput:output];
        //设置扫码支持的编码格式
        
        NSMutableArray *array = [[NSMutableArray alloc]initWithCapacity:0];
        
        if ([output.availableMetadataObjectTypes containsObject:AVMetadataObjectTypeQRCode]) {
            [array addObject:AVMetadataObjectTypeQRCode];
        }
        if ([output.availableMetadataObjectTypes containsObject:AVMetadataObjectTypeEAN13Code]) {
            [array addObject:AVMetadataObjectTypeEAN13Code];
        }
        if ([output.availableMetadataObjectTypes containsObject:AVMetadataObjectTypeEAN8Code]) {
            [array addObject:AVMetadataObjectTypeEAN8Code];
        }
        if ([output.availableMetadataObjectTypes containsObject:AVMetadataObjectTypeCode128Code]) {
            [array addObject:AVMetadataObjectTypeCode128Code];
        }
        output.metadataObjectTypes = array;
        
    }
    
    AVCaptureVideoPreviewLayer *layer = [AVCaptureVideoPreviewLayer layerWithSession:_session];
    layer.videoGravity = AVLayerVideoGravityResizeAspectFill;
    layer.frame = self.bounds;
    [self.layer insertSublayer:layer above:0];
    [self bringSubviewToFront:_scanView];
    [self setOverView];
    [_session startRunning];
    [self loopDrawLine];
    
    
}

- (CGRect)rectOfInterestByScanViewRect:(CGRect)rect{
    
    CGFloat width = CGRectGetWidth(self.frame);
    CGFloat height = CGRectGetHeight(self.frame);
    
    CGFloat x = (height - CGRectGetHeight(rect))/2/height;
    CGFloat y = (width - CGRectGetWidth(rect))/2/width;
    
    CGFloat w = CGRectGetHeight(rect)/height;
    CGFloat h = CGRectGetWidth(rect)/width;
    
    return CGRectMake(x, y, w, h);
}

#pragma mark - 添加模糊效果
- (void)setOverView
{
    CGFloat width = CGRectGetWidth(self.frame);
    CGFloat height = CGRectGetHeight(self.frame);
    
    CGFloat x = CGRectGetMinX(_scanView.frame);
    CGFloat y = CGRectGetMinY(_scanView.frame);
    CGFloat w = CGRectGetWidth(_scanView.frame);
    CGFloat h = CGRectGetHeight(_scanView.frame);
    
    [self creatView:CGRectMake(0, 0, width, y)];
    [self creatView:CGRectMake(0, y + h, width, height - y)];
    [self creatView:CGRectMake(0, y, x, h)];
    [self creatView:CGRectMake(x + w, y, x, h)];
    
}

- (void)creatView:(CGRect)rect{
    CGFloat alpha = 0.5;
    UIView *view = [[UIView alloc]initWithFrame:rect];
    view.backgroundColor = [UIColor grayColor];
    view.alpha = alpha;
    [self addSubview:view];
}

#pragma mark - 动画
- (void)loopDrawLine {
    
    UIImage *lineImage = [UIImage imageNamed:@"scanLine"];
    
    CGFloat x = CGRectGetMinX(_scanView.frame);
    CGFloat y = CGRectGetMinY(_scanView.frame);
    CGFloat w = CGRectGetWidth(_scanView.frame);
    CGFloat h = CGRectGetHeight(_scanView.frame);
    
    CGRect start = CGRectMake(x, y, w, 2);
    CGRect end = CGRectMake(x, y + h - 2, w, 2);
    
    if (!_lineView) {
        _lineView = [[UIImageView alloc]initWithImage:lineImage];
        _lineView.frame = start;
        [self addSubview:_lineView];
    }else{
        _lineView.frame = start;
    }
    
    __weak typeof(self) weakSelf = self;
    [UIView animateWithDuration:2 animations:^{
        _lineView.frame = end;
    } completion:^(BOOL finished) {
        [weakSelf loopDrawLine];
    }];
}

#pragma mark - AVCaptureMetadataOutputObjectsDelegate
- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputMetadataObjects:(NSArray *)metadataObjects fromConnection:(AVCaptureConnection *)connection
{
    if (metadataObjects.count>0) {
        AVMetadataMachineReadableCodeObject *metadataObject = [metadataObjects firstObject];
        if ([_delegate respondsToSelector:@selector(qrView:ScanResult:)]) {
            [_delegate qrView:self ScanResult:metadataObject.stringValue];
        }
    }
}

- (void)startScan{
    _lineView.hidden = NO;
    [_session startRunning];
}

- (void)stopScan{
    _lineView.hidden = YES;
    
    [_session stopRunning];
}

@end


最后在 ControllerView 中引入上面的. h 文件

1,第一步:初始化 QRView 的视图 (别忘了遵守QRViewDelegate> 的代理方法 并且实现它

#import "QRCodeVC.h"
#import "QRView.h"


@interface QRCodeVC ()<QRViewDelegate>


@end

@implementation QRCodeVC

- (void)viewDidLoad {
    [super viewDidLoad];
    
    self.navigationController.navigationItem.title = @"扫一扫";
    self.view.backgroundColor = [UIColor whiteColor];
    
    QRView *qrview = [[QRView alloc] initWithFrame:self.view.bounds];
    
    // 设置代理
    qrview.delegate = self;
    
    [self.view addSubview:qrview];
    

    

}
#pragma mark --- 实现代理方法

// 代理回调结果
- (void)qrView:(QRView *)View ScanResult:(NSString *)result
{
    [View stopScan];
    
    UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"提示" message:nil preferredStyle:UIAlertControllerStyleAlert];
    [alert addAction:[UIAlertAction actionWithTitle:@"跳转" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
        [[UIApplication sharedApplication] openURL:[NSURL URLWithString:result]];
        [View startScan];
        
    }]];
       [self presentViewController:alert animated:true completion:^{
        
        
    }];
    
    NSLog(@"扫描结果:%@",result);
}





  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值