zoukankan      html  css  js  c++  java
  • 扫描功能小结 (扫描二维码、条形码)

    此次扫码功能以iOS系统原生的AVFoundation框架为基础。

    废话不多说,直接上代码

    #import <UIKit/UIKit.h>
    
    @interface ScanViewController : UIViewController
    
    @end
    创建扫描界面

    在.m文件中创建对象

    #import "ScanViewController.h"
    #import <AVFoundation/AVFoundation.h>
    
    #import "UserInputCodeViewController.h"
    #import "ScanResultViewController.h"
    
    @interface ScanViewController ()<AVCaptureMetadataOutputObjectsDelegate>
    
    @property (nonatomic, strong) AVCaptureDevice *device;
    
    @property (nonatomic, strong) AVCaptureDeviceInput *input;
    
    @property (nonatomic, strong) AVCaptureMetadataOutput *output;
    
    @property (nonatomic, strong) AVCaptureSession *session;
    
    @property (nonatomic, strong) AVCaptureVideoPreviewLayer *previewLayer;
    
    /*** 专门用于保存描边的图层 ***/
    @property (nonatomic,strong) CALayer *containerLayer;
    /**
     扫描范围
     */
    @property(nonatomic, strong) UIView *scanFrame;
    @property(nonatomic, strong) UIView *line;
    
    //@property (nonatomic, strong) UIImageView *scanArea;
    @property (nonatomic, strong) UILabel *lightLb;
    
    /**
     是否打开灯光
     */
    @property (nonatomic, assign) BOOL isLightOn;
    
    @end
    
    @implementation ScanViewController
    
    -(void)viewWillAppear:(BOOL)animated {
        [super viewWillAppear:animated];
        if (!_session ) {
            [self startScan];
        }
        [self refreshScanLineAnimation];
    }
    
    -(void)refreshScanLineAnimation {
        if (_line) {
            [self scanLineAnimate];
        }
    }
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        // Do any additional setup after loading the view.
        self.title = @"扫码开锁";
        self.view.backgroundColor = [UIColor whiteColor];
        
        _isLightOn = NO;
        
        [self initViews];
        
        [self initConner];
        
        [self startScan];
    }
    
    -(void)initViews {
        CGRect frame = CGRectZero;
        
        frame.origin.x = (SCREEN_WIDTH - 230) / 2;
        frame.origin.y = (SCREEN_HEIGHT - 500) / 2;
        frame.size.width = 230;
        frame.size.height= 230;
        
        UIView* view = [[UIView alloc] initWithFrame:frame];
        view.backgroundColor= [UIColor clearColor];
        view.layer.borderWidth = 1;
        view.layer.borderColor = [[UIColor grayColor] CGColor];
        self.scanFrame = view;
        [self.view addSubview:view];
        
        //top
        UIView* shadow = [[UIView alloc] initWithFrame:CGRectMake(0, 0, SCREEN_WIDTH, view.frame.origin.y)];
        shadow.backgroundColor = [UIColor blackColor];
        shadow.alpha = 0.5;
        [self.view addSubview:shadow];
        
        //bottom
        shadow = [[UIView alloc] initWithFrame:CGRectMake(0, view.frame.origin.y + view.frame.size.height, SCREEN_WIDTH, SCREEN_HEIGHT - (view.frame.origin.y + view.frame.size.height))];
        shadow.backgroundColor = [UIColor blackColor];
        shadow.alpha = 0.5;
        [self.view addSubview:shadow];
        
        //left
        shadow = [[UIView alloc] initWithFrame:CGRectMake(0, view.frame.origin.y, (SCREEN_WIDTH - view.frame.size.width) / 2, view.frame.size.height)];
        shadow.backgroundColor = [UIColor blackColor];
        shadow.alpha = 0.5;
        [self.view addSubview:shadow];
        
        //right
        shadow = [[UIView alloc] initWithFrame:CGRectMake(view.frame.origin.x + view.frame.size.width, view.frame.origin.y, (SCREEN_WIDTH - view.frame.size.width) / 2, view.frame.size.height)];
        shadow.backgroundColor = [UIColor blackColor];
        shadow.alpha = 0.5;
        [self.view addSubview:shadow];
        
        _line = [[UIView alloc] initWithFrame:CGRectMake(view.frame.origin.x + 1, view.frame.origin.y + 1, frame.size.width - 2, 3)];
        _line.backgroundColor = UIColorFromRGB(0x28a0f0);
        [self.view addSubview:_line];
        
        UILabel* label = [[UILabel alloc] initWithFrame:CGRectMake(0, CGRectGetMaxY(view.frame) + HEIGTHCUSTOME(70), _line.frame.size.width, 15)];
        label.font = UIFontWithPX(26);
        label.textColor = [UIColor whiteColor];
        label.textAlignment = NSTextAlignmentCenter;
        label.center = CGPointMake(_line.center.x, label.center.y);
        label.text = @"请对准充电箱上的二维码";
        [self.view addSubview:label];
        
        //light
        UIButton* light = [UIButton buttonWithType:UIButtonTypeCustom];
        light.frame = CGRectMake(0, view.frame.origin.y + view.frame.size.height + 120, 100, 100);
    //    light.center = CGPointMake(view.frame.origin.x + view.frame.size.width - 50, light.center.y);
        light.center = CGPointMake(view.center.x, light.center.y);
        light.backgroundColor = [UIColor clearColor];
        [light setImage:IMAGE(@"flashlight_off") forState:UIControlStateNormal];
        [light addTarget:self action:@selector(openLight:) forControlEvents:UIControlEventTouchUpInside];
        [self.view addSubview:light];
        
        _lightLb = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 100, 20)];
        _lightLb.center = CGPointMake(light.center.x, light.center.y + 50);
        _lightLb.text = @"打开手电筒";
        _lightLb.textAlignment = NSTextAlignmentCenter;
        _lightLb.textColor = [UIColor whiteColor];
        _lightLb.font = [UIFont systemFontOfSize:14];
        [self.view addSubview:_lightLb];
    }
    
    - (void)initConner {
        CGFloat w = 2;
        CGFloat h = 10;
        CGFloat d = 2;
        CGPoint point = CGPointZero;
        
        //left - top
        point = CGPointMake(_scanFrame.frame.origin.x - w - d, _scanFrame.frame.origin.y - w - d);
        UIView* view = [[UIView alloc] initWithFrame:CGRectMake(point.x, point.y, w, h)];
        view.backgroundColor = UIColorFromRGB(0x28a0f0);
        [self.view addSubview:view];
        
        view = [[UIView alloc] initWithFrame:CGRectMake(point.x, point.y, h, w)];
        view.backgroundColor = UIColorFromRGB(0x28a0f0);
        [self.view addSubview:view];
        
        //left - down
        point = CGPointMake(_scanFrame.frame.origin.x - w - d, _scanFrame.frame.origin.y + _scanFrame.frame.size.height + d + w - h);
        view = [[UIView alloc] initWithFrame:CGRectMake(point.x, point.y, w, h)];
        view.backgroundColor = UIColorFromRGB(0x28a0f0);
        [self.view addSubview:view];
        
        point = CGPointMake(point.x, _scanFrame.frame.origin.y + _scanFrame.frame.size.height + d);
        view = [[UIView alloc] initWithFrame:CGRectMake(point.x, point.y, h, w)];
        view.backgroundColor = UIColorFromRGB(0x28a0f0);
        [self.view addSubview:view];
        
        //right - top
        point = CGPointMake(_scanFrame.frame.origin.x + _scanFrame.frame.size.width + d, _scanFrame.frame.origin.y - w - d);
        view = [[UIView alloc] initWithFrame:CGRectMake(point.x, point.y, w, h)];
        view.backgroundColor = UIColorFromRGB(0x28a0f0);
        [self.view addSubview:view];
        
        point = CGPointMake(_scanFrame.frame.origin.x + _scanFrame.frame.size.width + w + d - h, point.y);
        view = [[UIView alloc] initWithFrame:CGRectMake(point.x, point.y, h, w)];
        view.backgroundColor = UIColorFromRGB(0x28a0f0);
        [self.view addSubview:view];
        
        //right - down
        point = CGPointMake(_scanFrame.frame.origin.x + _scanFrame.frame.size.width + d, _scanFrame.frame.origin.y + _scanFrame.frame.size.height + w + d - h);
        view = [[UIView alloc] initWithFrame:CGRectMake(point.x, point.y, w, h)];
        view.backgroundColor = UIColorFromRGB(0x28a0f0);
        [self.view addSubview:view];
        
        point = CGPointMake(point.x + w - h, _scanFrame.frame.origin.y + _scanFrame.frame.size.height + d);
        view = [[UIView alloc] initWithFrame:CGRectMake(point.x, point.y, h, w)];
        view.backgroundColor = UIColorFromRGB(0x28a0f0);
        [self.view addSubview:view];
    }
    
    - (void)scanLineAnimate {
        [UIView beginAnimations:nil context:nil];
        [UIView setAnimationDuration:2];
        [UIView setAnimationCurve:UIViewAnimationCurveLinear];
        [UIView setAnimationRepeatAutoreverses:YES];
        [UIView setAnimationRepeatCount:HUGE_VALF];
        _line.center = CGPointMake(_line.center.x, _scanFrame.frame.origin.y + _scanFrame.frame.size.height - 5);
        [UIView commitAnimations];
    }
    
    - (void)openLight:(UIButton*)sender {
        [_device lockForConfiguration:nil];
        if (!sender.selected) {
            [sender setImage:IMAGE(@"flashlight_on") forState:UIControlStateNormal];
            [_device setTorchMode:AVCaptureTorchModeOn];
            [_device setFlashMode:AVCaptureFlashModeOn];
            _lightLb.text = @"关闭手电筒";
            sender.selected = YES;
        } else {
            [sender setImage:IMAGE(@"flashlight_off") forState:UIControlStateNormal];
            [_device setTorchMode:AVCaptureTorchModeOff];
            [_device setFlashMode:AVCaptureFlashModeOff];
            _lightLb.text = @"打开手电筒";
            sender.selected = NO;
        }
        [_device unlockForConfiguration];
    }
    
    - (void)startScan {
        if (![self.session canAddInput:self.input]) return;
        [self.session addInput:self.input];
        
        if (![self.session canAddOutput:self.output]) return;
        [self.session addOutput:self.output];
        
    //    self.output.metadataObjectTypes = self.output.availableMetadataObjectTypes;     // 如此设置,可扫描二维码、条形码
        [self.output setMetadataObjectTypes:@[AVMetadataObjectTypeQRCode]];
        
        [self.output setMetadataObjectsDelegate:self queue:dispatch_get_main_queue()];
        
        [self.view.layer insertSublayer:self.previewLayer atIndex:0];
        
        [self.view.layer addSublayer:self.containerLayer];
       
        [self.session startRunning];
    }
    
    - (void)drawLine:(AVMetadataMachineReadableCodeObject *)objc {
        NSArray *array = objc.corners;
        
        CAShapeLayer *layer = [[CAShapeLayer alloc] init];
        layer.lineWidth = 2;
        layer.strokeColor = [UIColor greenColor].CGColor;
        layer.fillColor = [UIColor clearColor].CGColor;
        
        UIBezierPath *path = [[UIBezierPath alloc] init];
        CGPoint point = CGPointZero;
        int index = 0;
        
        CFDictionaryRef dict = (__bridge CFDictionaryRef)(array[index++]);
        CGPointMakeWithDictionaryRepresentation(dict, &point);
        
        [path moveToPoint:point];
        
        for (int i = 1; i<array.count; i++) {
            CGPointMakeWithDictionaryRepresentation((__bridge CFDictionaryRef)array[i], &point);
            [path addLineToPoint:point];
        }
        [path closePath];
        layer.path = path.CGPath;
        [self.containerLayer addSublayer:layer];
    }
    
    - (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputMetadataObjects:(NSArray *)metadataObjects fromConnection:(AVCaptureConnection *)connection {
        if (_session) {
            [_session stopRunning];
        }
        [_output setMetadataObjectsDelegate:nil queue:dispatch_get_main_queue()];
        
        // id 类型不能点语法,所以要先去取出数组中对象
        id object = [metadataObjects lastObject];
        if ([object isKindOfClass:[AVMetadataMachineReadableCodeObject class]]) {
            NSString *stringValue;
            if ([metadataObjects count] >0) {
                AVMetadataMachineReadableCodeObject * metadataObject = [metadataObjects lastObject];
                stringValue = metadataObject.stringValue;
            }
            
            [self judgeCode:stringValue];
    //        [self judgeCode:@"test00001"];
            
            [self clearLayers];
            AVMetadataMachineReadableCodeObject *obj = (AVMetadataMachineReadableCodeObject *)[self.previewLayer transformedMetadataObjectForMetadataObject:object];
            [self drawLine:obj];
        }
    }
    // 初始化扫描界面
    -(void)initPreviewImg {
        [_output setMetadataObjectsDelegate:nil queue:dispatch_get_main_queue()];
        [_session stopRunning];
        [_session removeOutput:_output];
        [_session removeInput:_input];
        
        [_containerLayer removeFromSuperlayer];
        [_previewLayer removeFromSuperlayer];
        
        _containerLayer = nil;       //不置空,二维码的彩色边框无法去除
        _session = nil;                 // 不置空,返回本页面,出现白屏
        _output = nil;
        _previewLayer = nil;        // 不置空,会有空指针,由下个界面返回时会出现崩溃
        /*
         Assertion failed: (_inputInternal->figCaptureSession == NULL), function __44-[AVCaptureInput attachToFigCaptureSession:]_block_invoke, file /BuildRoot/Library/Caches/com.apple.xbs/Sources/EmbeddedAVFoundation/EmbeddedAVFoundation-1184.7/Aspen/AVCaptureInput.m, line 132.
         */
    }
    
    - (void)clearLayers {
        if (self.containerLayer.sublayers) {
            for (CALayer *subLayer in self.containerLayer.sublayers) {
                [subLayer removeFromSuperlayer];
            }
        }
    }
    #pragma mark -------- 懒加载---------
    - (AVCaptureDevice *)device {
        if (_device == nil) {
            _device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
        }
        return _device;
    }
    
    - (AVCaptureDeviceInput *)input {
        if (_input == nil) {
            _input = [AVCaptureDeviceInput deviceInputWithDevice:self.device error:nil];
        }
        return _input;
    }
    
    - (AVCaptureSession *)session {
        if (_session == nil) {
            _session = [[AVCaptureSession alloc] init];
        }
        return _session;
    }
    
    - (AVCaptureVideoPreviewLayer *)previewLayer {
        if (_previewLayer == nil) {
            _previewLayer = [AVCaptureVideoPreviewLayer layerWithSession:self.session];
            _previewLayer.frame = self.view.bounds;
        }
        return _previewLayer;
    }
    
    - (AVCaptureMetadataOutput *)output {
        if (_output == nil) {
            _output = [[AVCaptureMetadataOutput alloc] init];
            CGRect viewRect = self.view.frame;
            CGRect containerRect = _scanFrame.frame;
            CGFloat x = containerRect.origin.y / viewRect.size.height;
            CGFloat y = containerRect.origin.x / viewRect.size.width;
            CGFloat width = containerRect.size.height / viewRect.size.height;
            CGFloat height = containerRect.size.width / viewRect.size.width;
            _output.rectOfInterest = CGRectMake(x, y, width, height);
        }
        return _output;
    }
    
    - (CALayer *)containerLayer {
        if (_containerLayer == nil) {
            _containerLayer = [[CALayer alloc] init];
            _containerLayer.frame = self.view.bounds;
        }
        return _containerLayer;
    }
    
    - (void)didReceiveMemoryWarning {
        [super didReceiveMemoryWarning];
        // Dispose of any resources that can be recreated.
    }
    
    @end
    创建对象
  • 相关阅读:
    [蓝桥杯][算法提高VIP]传染病控制
    PAT甲级第二次真题练习
    BFS()搜索加上hash
    PAT甲级第一次真题练习
    一个小练习题
    八皇后
    【Noi 1994 删数问题】【openjudge 3528 最小新整数(变式)】整型与字符
    【openjudge 2469 电池的寿命】算法与思维
    MarkDown测试
    HNOI 2017 怼大佬
  • 原文地址:https://www.cnblogs.com/linzhengbo/p/6831159.html
Copyright © 2011-2022 走看看