iOS 扫一扫二维码(原生)

192 阅读2分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

.h

//

#import <UIKit/UIKit.h>
#import <AVFoundation/AVFoundation.h>
@interface JKScannerViewController : UIViewController<AVCaptureMetadataOutputObjectsDelegate,UIAlertViewDelegate>
{
    int num;
    BOOL upOrdown;
    NSTimer * timer;
    UIImageView * imageView;
    
    BOOL hasCameraRight;
}
@property (strong,nonatomic)AVCaptureDevice * device;
@property (strong,nonatomic)AVCaptureDeviceInput * input;
@property (strong,nonatomic)AVCaptureMetadataOutput * output;
@property (strong,nonatomic)AVCaptureSession * session;
@property (strong,nonatomic)AVCaptureVideoPreviewLayer * preview;
@property (nonatomic, retain) UIImageView * line;
@end

//扫一扫 页面


.m

//

//
//  Created by bwrc on 17/6/5.
//  Copyright © 2017年 bwrc. All rights reserved.
//

#import "JKScannerViewController.h"
#import "ViewUtils.h"
@interface JKScannerViewController ()
@property (nonatomic, strong) UIButton *flashlightBtn;
@end

@implementation JKScannerViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.
    [super viewDidLoad];
    
    self.title = @"扫一扫";
    self.view.backgroundColor = [UIColor blackColor];
    
    //明暗对比
    UIView *maskView = [[UIView alloc] initWithFrame:self.view.bounds];
    
    maskView.backgroundColor = [UIColor colorWithRed:0 green:0 blue:0 alpha:0.5];
    
    [self.view addSubview:maskView];
    
    UIBezierPath *maskPath = [UIBezierPath bezierPathWithRect:CGRectMake(0, 0, widthScreen, heightScreen)];
    
    [maskPath appendPath:[[UIBezierPath bezierPathWithRoundedRect:CGRectMake(50, 50+ 64,widthScreen - 100, widthScreen - 100) cornerRadius:1] bezierPathByReversingPath]];
    
    CAShapeLayer *maskLayer = [[CAShapeLayer alloc] init];
    
    maskLayer.path = maskPath.CGPath;
    
    maskView.layer.mask = maskLayer;
    

    
    
    NSString *mediaType = AVMediaTypeVideo;
    
    AVAuthorizationStatus authStatus = [AVCaptureDevice authorizationStatusForMediaType:mediaType];
    
    if(authStatus == AVAuthorizationStatusRestricted || authStatus == AVAuthorizationStatusDenied){
        
       
        UIAlertController *alert=[UIAlertController alertControllerWithTitle:@"没有相机权限" message:@"请去设置-隐私-相机中对扫一扫授权" preferredStyle:UIAlertControllerStyleAlert];
        
        UIAlertAction *action2=[UIAlertAction actionWithTitle:@"好的" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action2){
            
            [self.navigationController popViewControllerAnimated:YES];
            
        }];
       
        [alert addAction:action2];
        //5.将警告呈现出来
        [self presentViewController:alert animated:YES completion:nil];
        hasCameraRight = NO;
        return;
    }
    hasCameraRight = YES;
    
    imageView = [[UIImageView alloc]initWithFrame:CGRectMake(50, 50+ 64,widthScreen - 100, widthScreen - 100)];
    imageView.image = [UIImage imageNamed:@"contact_scanframe"];
    [self.view addSubview:imageView];
   
    
    UILabel * introudctionLB= [[UILabel alloc] initWithFrame:CGRectMake(50, imageView.bottom + 20, widthScreen - 100, 30)];
    introudctionLB.backgroundColor = [UIColor clearColor];
    introudctionLB.textColor=[UIColor whiteColor];
    introudctionLB.font = [UIFont systemFontOfSize:13];
    introudctionLB.textAlignment = NSTextAlignmentCenter;
    introudctionLB.text=@"将取景框对准二维码,即可自动扫描";
    [self.view addSubview:introudctionLB];
    
    self.flashlightBtn = [[UIButton alloc]initWithFrame:CGRectMake(widthScreen/2 - 20, introudctionLB.bottom + 20, 40, 40)];
    [self.flashlightBtn setTitle:@"手电" forState:UIControlStateNormal];
    [self.flashlightBtn addTarget:self action:@selector(flashlightBtnAction:) forControlEvents:UIControlEventTouchUpInside];
    [self.view addSubview:self.flashlightBtn];
    
    
    upOrdown = NO;
    num =0;
    _line = [[UIImageView alloc] initWithFrame:CGRectMake(50, 50+ 64 + 8, widthScreen - 100 - 40, 2)];
    _line.x = self.view.x;
    _line.image = [UIImage imageNamed:@"line"];
    [self.view addSubview:_line];
    
    
    [self setupCamera];
}
-(void)flashlightBtnAction:(UIButton *)sender {//闪光灯
    Class captureDeviceClass = NSClassFromString(@"AVCaptureDevice");
    
    if (captureDeviceClass != nil) {
        
        AVCaptureDevice *device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
        
        if ([device hasTorch]) { // 判断是否有闪光灯
            
            // 请求独占访问硬件设备
            
            [device lockForConfiguration:nil];
            
            if (sender.tag == 0) {
                
                
                sender.tag = 1;
                
                [device setTorchMode:AVCaptureTorchModeOn]; // 手电筒开
                
            }else{
                
                
                sender.tag = 0;
                
                [device setTorchMode:AVCaptureTorchModeOff]; // 手电筒关
                
            }
            
            // 请求解除独占访问硬件设备
            
            [device unlockForConfiguration];
            
        }
        
    }
}

-(void)animation1
{
    if (upOrdown == NO) {
        num ++;
        _line.frame = CGRectMake(CGRectGetMinX(_line.frame), 50+ 64 + 8+2*num, CGRectGetWidth(_line.frame), CGRectGetHeight(_line.frame));
        if (2 * num >= CGRectGetHeight(imageView.frame) - 16) {
            upOrdown = YES;
        }
    }
    else {
        num --;
        _line.frame = CGRectMake(CGRectGetMinX(_line.frame), 50+ 64 + 8+2*num, CGRectGetWidth(_line.frame), CGRectGetHeight(_line.frame));
        if (num == 0) {
            upOrdown = NO;
        }
    }
    
}



-(void)viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:animated];
    
    if (hasCameraRight) {
        if (_session && ![_session isRunning]) {
            [_session startRunning];
        }
        timer = [NSTimer scheduledTimerWithTimeInterval:.02 target:self selector:@selector(animation1) userInfo:nil repeats:YES];
    }
}

- (void)viewWillDisappear:(BOOL)animated
{
    [super viewWillDisappear:animated];
    [timer invalidate];
}

- (void)setupCamera
{
    
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        // 耗时的操作
        // Device
        _device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
        
        // Input
        _input = [AVCaptureDeviceInput deviceInputWithDevice:self.device error:nil];
        
        // Output
        _output = [[AVCaptureMetadataOutput alloc]init];
        //    [_output setMetadataObjectsDelegate:self queue:dispatch_get_main_queue()];
        
   
       
        [_output setMetadataObjectsDelegate:self queue:dispatch_get_main_queue()];
        
        // 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.metadataObjectTypes = @[AVMetadataObjectTypeQRCode,AVMetadataObjectTypeEAN13Code, AVMetadataObjectTypeEAN8Code, AVMetadataObjectTypeCode128Code];
        dispatch_async(dispatch_get_main_queue(), ^{
            // 更新界面
            // Preview
            _preview =[AVCaptureVideoPreviewLayer layerWithSession:self.session];
            _preview.videoGravity = AVLayerVideoGravityResizeAspectFill;
            //    _preview.frame =CGRectMake(20,110,280,280);
            _preview.frame = self.view.bounds;
            
            [self.view.layer insertSublayer:self.preview atIndex:0];
            // Start
            [_session startRunning];
        
            CGRect intertRect = [_preview metadataOutputRectOfInterestForRect:imageView.frame];
            
            //限制区域
            [ _output setRectOfInterest : intertRect];
           
        });
    });
}

#pragma mark AVCaptureMetadataOutputObjectsDelegate
- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputMetadataObjects:(NSArray *)metadataObjects fromConnection:(AVCaptureConnection *)connection
{
    
    NSString *stringValue;
    
    if ([metadataObjects count] >0)
    {
        AVMetadataMachineReadableCodeObject * metadataObject = [metadataObjects objectAtIndex:0];
        stringValue = metadataObject.stringValue;
        
        [_session stopRunning];
        [timer invalidate];
        NSLog(@"%@",stringValue);
        
        if (stringValue.length > 0) {
            
            UIAlertController *alert=[UIAlertController alertControllerWithTitle:@"扫描结果" message:@"只能扫面展商名片" preferredStyle:UIAlertControllerStyleAlert];
           
            UIAlertAction *action2=[UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action2){
              
                [self.navigationController popViewControllerAnimated:YES];
            }];
                    [alert addAction:action2];
            //5.将警告呈现出来
            [self presentViewController:alert animated:YES completion:nil];
            
        }
    }
    
}

@end