iOS 原生二维码扫描

直接上项目代码 

首先检查相机权限  

AVAuthorizationStatus status = [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo];
if (status == AVAuthorizationStatusRestricted || status == AVAuthorizationStatusDenied) {
    // 没有授权访问相机权限 提示
    return;
}


#import "QrCodeVC.h"
#import <AVFoundation/AVFoundation.h>
#import <Masonry/Masonry.h>
#import <pop/POP.h>
#import "AppDelegate.h"
#import "GoodsDetailVC.h"
#import "WebViewVC.h"

#define QRWH (ZKScreenW*283/375.0)
#define TOP (ZKScreenH-QRWH)/2.0
#define LEFT (ZKScreenW-QRWH)/2.0
#define kScanRect CGRectMake(LEFT, TOP, QRWH, QRWH)
#define kLineRect CGRectMake(LEFT+15, TOP, QRWH-30, 3)
const static CGFloat animationTime = 2.0f;//扫描时长
@interface QrCodeVC () <AVCaptureMetadataOutputObjectsDelegate>
{
    CAShapeLayer *cropLayer;
}
@property (nonatomic, strong) AVCaptureDevice *device;
@property (nonatomic, strong) AVCaptureDeviceInput *input;
@property (nonatomic, strong) AVCaptureMetadataOutput *output;
@property (nonatomic, strong) AVCaptureSession *session;
@property (nonatomic, strong) AVCaptureVideoPreviewLayer *preview;
/** 二维码View **/
@property (nonatomic, strong) UIImageView *qrImageView;
@property (nonatomic, strong) UIImageView *animationImageV;
@property (nonatomic, assign) BOOL animationUp;
@property (nonatomic, strong) UILabel *messageLb;
@end
@implementation QrCodeVC
- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];
    if (_session != nil) {
        [_session startRunning];
    }
    
    self.animationImageV.hidden = NO;
}
- (void)viewWillDisappear:(BOOL)animated {
    [super viewWillDisappear:animated];
//    if (_session != nil) {
//        [_session stopRunning];
//    }
    self.animationImageV.hidden = YES;
}
- (void)viewDidLoad {
    [super viewDidLoad];
    
    // 初始化扫描UI
    [self initView];
    
    // 初始化扫描二维码
    [self setupCamera];
}
- (void)initView {
    
    UIView *bgView = [[UIView alloc] initWithFrame:self.view.bounds];
    [self.view addSubview:bgView];
    bgView.backgroundColor = [UIColor clearColor];
    
    cropLayer = [[CAShapeLayer alloc] init];
    CGMutablePathRef path = CGPathCreateMutable();
    CGPathAddRect(path, nil, kScanRect);
    CGPathAddRect(path, nil, self.view.bounds);
    [cropLayer setFillRule:kCAFillRuleEvenOdd];
    [cropLayer setPath:path];
    [cropLayer setFillColor:[[UIColor blackColor] colorWithAlphaComponent:0.3].CGColor];
    [cropLayer setNeedsDisplay];
    [bgView.layer addSublayer:cropLayer];
    
    UIImageView *imageV = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"qrCode_bg"]];
    imageV.frame = kScanRect;
    [self.view addSubview:imageV];
    _qrImageView = imageV;
    
    UIImageView *animationImageV = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"qrCodeLine"]];
    animationImageV.frame = kLineRect;
    animationImageV.contentMode = UIViewContentModeScaleAspectFill;
    [self.view addSubview:animationImageV];
    _animationImageV = animationImageV;
    
    UILabel *messageLb = [[UILabel alloc] initWithFrame:CGRectMake(15, TOP-40, ZKScreenW-30, 20)];
    messageLb.text = getStringByKey(@"string_key_1592");
    messageLb.textAlignment = NSTextAlignmentCenter;
    messageLb.numberOfLines = 0;
    messageLb.font = [UIFont boldSystemFontOfSize:14];
    messageLb.textColor = [UIColor whiteColor];
    [self.view addSubview:messageLb];
    
    UILabel *titleLb = [[UILabel alloc] initWithFrame:CGRectMake(0, 30, ZKScreenW, 20)];
    titleLb.text = getStringByKey(@"string_key_1593");
    titleLb.textAlignment = NSTextAlignmentCenter;
    titleLb.font = [UIFont boldSystemFontOfSize:17];
    titleLb.textColor = [UIColor whiteColor];
    [self.view addSubview:titleLb];
    
    UIButton *backBtn = [[UIButton alloc] init];
    [backBtn setImage:[UIImage imageNamed:@"video_wirteBackArrow"] forState:UIControlStateNormal];
    [backBtn addTarget:self action:@selector(clickBackBtn) forControlEvents:UIControlEventTouchUpInside];
    [self.view addSubview:backBtn];
    [backBtn mas_makeConstraints:^(MASConstraintMaker *make) {
        make.top.equalTo(self.view.mas_top).with.offset(20);
        make.leading.equalTo(self.view.mas_leading);
        make.width.mas_equalTo(44);
        make.height.mas_equalTo(44);
    }];
}
- (void)clickBackBtn {
    [self.navigationController popViewControllerAnimated:YES];
}
- (CABasicAnimation *)qrAnimation {
    
    CGPoint starPoint = CGPointMake(_qrImageView.centerX  , _qrImageView.mj_y+3);
    CGPoint endPoint = CGPointMake(_qrImageView.centerX, _qrImageView.mj_y+QRWH-3);
    
    CABasicAnimation*translation = [CABasicAnimation animationWithKeyPath:@"position"];
    translation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear];
    
    translation.fromValue = [NSValue valueWithCGPoint:starPoint];
    translation.toValue = [NSValue valueWithCGPoint:endPoint];
    translation.duration = animationTime;
    translation.repeatCount = CGFLOAT_MAX;
    translation.autoreverses = YES;
    translation.removedOnCompletion = NO;
    
    return translation;
}
- (void)setupCamera {
    AVCaptureDevice *device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
    if (device==nil) {  // 设备没有摄像头
//        UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"提示" message:@"设备没有摄像头" preferredStyle:UIAlertControllerStyleAlert];
//        [alert addAction:[UIAlertAction actionWithTitle:@"确认" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
//
//        }]];
//        [self presentViewController:alert animated:YES completion:nil];
        return;
    }
    _device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
    _input = [AVCaptureDeviceInput deviceInputWithDevice:self.device error:nil];
    _output = [[AVCaptureMetadataOutput alloc]init];
    [_output setMetadataObjectsDelegate:self queue:dispatch_get_main_queue()];
    
    //设置扫描区域
    CGFloat top = TOP/ZKScreenH;
    CGFloat left = LEFT/ZKScreenW;
    CGFloat width = QRWH/ZKScreenW;
    CGFloat height = QRWH/ZKScreenH;
    ///top 与 left 互换  width 与 height 互换
    [_output setRectOfInterest:CGRectMake(top,left, height, width)];
    
    
    // Session
    _session = [[AVCaptureSession alloc]init];
    [_session setSessionPreset:AVCaptureSessionPresetHigh];
    if ([_session canAddInput:self.input]) {
        [_session addInput:self.input];
    }
    
    if ([_session canAddOutput:self.output]) {
        [_session addOutput:self.output];
    }
    
    // 条码类型 AVMetadataObjectTypeQRCode
    [_output setMetadataObjectTypes:[NSArray arrayWithObjects:AVMetadataObjectTypeQRCode, nil]];
    
    // Preview
    _preview =[AVCaptureVideoPreviewLayer layerWithSession:_session];
    _preview.videoGravity = AVLayerVideoGravityResizeAspectFill;
    _preview.frame =self.view.layer.bounds;
    [self.view.layer insertSublayer:_preview atIndex:0];
    
    [_session startRunning];
    
    [_animationImageV.layer addAnimation:[self qrAnimation] forKey:nil];
}
#pragma mark AVCaptureMetadataOutputObjectsDelegate
- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputMetadataObjects:(NSArray *)metadataObjects fromConnection:(AVCaptureConnection *)connection {
    NSString *stringValue;
    
    if ([metadataObjects count] >0) {
        //停止扫描
        [_session stopRunning];
        AVMetadataMachineReadableCodeObject *metadataObject = [metadataObjects objectAtIndex:0];
        stringValue = metadataObject.stringValue;
        if (stringValue.length > 0) {
            if ([stringValue containsString:@"sheinlink://applink/"]) {  // 调用deeplink跳转页面
                AppDelegate *appDelegate=(AppDelegate*)[UIApplication sharedApplication].delegate;
                [appDelegate openWithUrl:[NSURL URLWithString:stringValue]];
            } else if ([stringValue containsString:@"toApp"] && [stringValue containsString:@"goods_id="]) {  // 商品详情
                NSRange sizeRange= [stringValue rangeOfString:@"goods_id="];
                NSString *goodsId = [stringValue substringFromIndex:sizeRange.location+@"goods_id=".length];
                if (goodsId) {
                    GoodsInfo *goodsInfo=[[GoodsInfo alloc] init];
                    goodsInfo.goods_id=[goodsId intValue];
                    UIStoryboard *sb=[UIStoryboard storyboardWithName:@"Goods" bundle:[NSBundle mainBundle]];
                    GoodsDetailVC *vc=[sb instantiateViewControllerWithIdentifier:@"GoodsDetailVC"];
                    vc.goodsInfo=goodsInfo;
                    [self.navigationController pushViewController:vc animated:YES];
                }
            } else { // 跳转到普通网页
                UIStoryboard *sb=[UIStoryboard storyboardWithName:@"Setting" bundle:[NSBundle mainBundle]];
                WebViewVC *vc=[sb instantiateViewControllerWithIdentifier:@"WebViewVC"];
                vc.titleText = @"";
                vc.url = stringValue;
                [self.navigationController pushViewController:vc animated:YES];
            }
        } else {
            // 没有获取到url
        }
    } else {
        NSLog(@"无扫描信息");
        return;
    }
}

 

iOS 原生二维码扫描

上一篇:20180907-Java Applet基础


下一篇:Spring WebFlux 基础教程:参数校验