• ios开发原生的扫描二维码的实现以及限制扫描区域rectOfInterest遇到的一些坑


    早前面试的时候被问到扫描使用的是什么 脱口而出用的Zbar ,然后就问为何不用原生的,效率更高啊,话说刚开始干那时候只求实现,不求效率,也不知怎么的回答。现在回想,最好的回答就是: 需要相册扫描,原生的实现不了啊。

    ZBar 优点: 可以实现相册相片扫描 但是效率有点低.

    原生的: 效率高,但是不能做相册扫描.

    下面放代码

    做了些许优化

    主要体现在,首次进入扫一扫vc 启动扫一扫的代码放在了

    -(void)viewDidAppear:(BOOL)animated ,便于先进入在启动,不会给人卡的感觉.然后进入这个页面设置背景为黑色,当扫一扫启动ok的时候在把 背景设备为白色, 也有的在等待的时间内给他一个等待动画. 

    ios开发设置rectOfInterest不管用

    接下来说的就是扫一扫区域限制的问题

    首先属性大家基本都知道

    AVCaptureMetadataOutput 的对象的属性 rectOfInterest

    output.rectOfInterest=CGRectMake(100/height, (width/2 -110)/width, 220/height, 220/width);//width指的是AVCaptureVideoPreviewLayer 对象的宽度   height指的是AVCaptureVideoPreviewLayer 对象的高度

    //CGRectMake(y/deviceHeight, x/deviceWidth, height/deviceHeight, width/deviceWidth);

    解释下CGRectMake写法:都把x y width height 互换 了的.你扫一扫的那个框框的  起点坐标为 x  y 宽为width 高为height  ,deviceHeight ,deviceWidth指的是AVCaptureVideoPreviewLayer对象的高度但是写的时候如上,经过多次测试所得数据.大部分的宽度跟高度是相等的,但是在这里的比例是不相等的, 因为手机宽高不等. 好了接下来直接上代码.解释的不到位的就结合代码看吧.

    //.h

    #import <UIKit/UIKit.h>

    @interface ScanCodeViewController : UIViewController

    @property(nonatomic,strong)NSString *frameWhere;

    @property(strong,nonatomic)void(^getSysString)(NSString*);

    @end

    //.m

    #import "ScanCodeViewController.h"

    #import <AVFoundation/AVFoundation.h>

    #define widthMainControl [UIScreen mainScreen].bounds.size.width

    #define heightMainControl [UIScreen mainScreen].bounds.size.height

    #define colorMainBG [UIColor colorWithRed:253/255.0 green:199/255.0 blue:117/255.0 alpha:1]

    @interface ScanCodeViewController ()<AVCaptureMetadataOutputObjectsDelegate>

    {

        AVCaptureSession * session;//输入输出的中间桥梁

        int  startY;

        int topHeight;

        BOOL onceScan;

    }

    @property (strong, nonatomic) UIImageView *lineImg;

    @property(nonatomic,strong)NSTimer *scanLineTimer;

    @end

    @implementation ScanCodeViewController

    - (void)viewDidLoad {

        [super viewDidLoad];

        self.title = @"扫一扫";

        self.view.backgroundColor = [UIColor blackColor];

        onceScan = YES;

        int screenHeigth = (int)(heightMainControl);

        topHeight = 100;

        if (screenHeigth == 480) {

            topHeight = 50;

        }else if (screenHeigth == 568){

            topHeight = 60;

        }

    }

    -(void)makeUI

    {

        

        self.view.backgroundColor = [UIColor whiteColor];

        UIImageView *kaungImg = [[UIImageView alloc] initWithFrame:CGRectMake(self.view.frame.size.width/2 -110, topHeight, 220, 220)];

        kaungImg.image = [UIImage imageNamed:@"sys-k"];

        [self.view addSubview:kaungImg];

        

        self.lineImg = [[UIImageView alloc] initWithFrame:CGRectMake(self.view.frame.size.width/2 -100, topHeight + 10, 200, 7)];

        self.lineImg.image = [UIImage imageNamed:@"sys-ht"];

        [self.view addSubview:self.lineImg];

        

        for (int i=0 ; i< 4; i++) {

        UIView *leftView = [[UIView alloc] initWithFrame:CGRectMake(widthMainControl/2 - 110, 0, widthMainControl/2 - 110, 100)];

            if (i == 0) {

                leftView.frame = CGRectMake(0, 0, widthMainControl/2 - 110, heightMainControl - 64 + 64);

            }else if (i == 1){

                leftView.frame = CGRectMake(widthMainControl/2 - 110, 0, 220, topHeight);

            }else if (i == 2){

                leftView.frame = CGRectMake(widthMainControl/2 - 110 + 220, 0, widthMainControl/2 - 110, heightMainControl - 64 + 64);

            }else if (i == 3){

                leftView.frame = CGRectMake(widthMainControl/2 - 110, topHeight + 220, 220, heightMainControl - 64 - 220 - topHeight + 64);

            }

            

        leftView.backgroundColor = [UIColor blackColor];

        leftView.alpha = 0.4;

        [self.view addSubview:leftView];

            }

        

        

        //手动输入设备Id的按钮

        UIButton *hangBtn = [UIButton buttonWithType:UIButtonTypeRoundedRect];

        [hangBtn setTitle:@"取消" forState:UIControlStateNormal];

        hangBtn.frame = CGRectMake(self.view.frame.size.width/2 -110, topHeight + 270, 220, 40);

        [hangBtn addTarget:self action:@selector(pushToNextVC) forControlEvents:UIControlEventTouchUpInside];

        hangBtn.layer.cornerRadius = 5;

        [hangBtn setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];

        hangBtn.layer.masksToBounds = YES;

        hangBtn.backgroundColor = colorMainBG;

        [self.view addSubview:hangBtn];

        

        [self createTimer];

    }

    -(void)pushToNextVC

    {

        [self dismissViewControllerAnimated:YES completion:nil];

    //    AddDeviceByHandViewController *addDevice = [[AddDeviceByHandViewController alloc] init];

    //    [self.navigationController pushViewController:addDevice animated:YES];

    }

    -(void)viewDidAppear:(BOOL)animated

    {

        

        [UIView animateWithDuration:0.3 animations:^{

            self.view.backgroundColor = [UIColor whiteColor];

        }];

        

        //获取摄像设备

        AVCaptureDevice * device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];

        //创建输入流

        AVCaptureDeviceInput * input = [AVCaptureDeviceInput deviceInputWithDevice:device error:nil];

        //创建输出流

        

        AVCaptureMetadataOutput * output = [[AVCaptureMetadataOutput alloc]init];

        //设置代理 在主线程里刷新

        [output setMetadataObjectsDelegate:self queue:dispatch_get_main_queue()];

        

        float width = self.view.frame.size.width;// AVCaptureVideoPreviewLayer的对象的宽度

        float height = self.view.frame.size.height;// AVCaptureVideoPreviewLayer的对象的高度

        output.rectOfInterest=CGRectMake(100/height, (width/2 -110)/width, 220/height, 220/width);

        //CGRectMake(y, x, height, width);

        //初始化链接对象

        session = [[AVCaptureSession alloc]init];

        //高质量采集率

        [session setSessionPreset:AVCaptureSessionPresetHigh];

        

        [session addInput:input];

        [session addOutput:output];

        //设置扫码支持的编码格式(如下设置条形码和二维码兼容)

        output.metadataObjectTypes=@[AVMetadataObjectTypeQRCode,AVMetadataObjectTypeEAN13Code, AVMetadataObjectTypeEAN8Code, AVMetadataObjectTypeCode128Code];

        

        AVCaptureVideoPreviewLayer * layer = [AVCaptureVideoPreviewLayer layerWithSession:session];

        layer.videoGravity=AVLayerVideoGravityResizeAspectFill;

        layer.frame=self.view.layer.bounds;

        [self.view.layer insertSublayer:layer atIndex:0];

        //开始捕获

        [session startRunning];

        

        [self makeUI];

    }

    #define LINE_SCAN_TIME  0.01     // 扫描线从上到下扫描所历时间(s)

    - (void)createTimer {

        startY = 110 ;

        self.scanLineTimer =

        [NSTimer scheduledTimerWithTimeInterval:LINE_SCAN_TIME

                                         target:self

                                       selector:@selector(moveScanImg)

                                       userInfo:nil

                                        repeats:YES];

    }

    -(void)moveScanImg

    {

        int  startX = self.view.frame.size.width/2 -100;

        startY += 1;

        if (startY > topHeight + 210) {

            startY = topHeight + 10;

        }

        self.lineImg.frame = CGRectMake(startX,startY , 200, 7);

    }

    -(void)viewDidDisappear:(BOOL)animated

    {

        [self.scanLineTimer invalidate];

    }

    -(void)captureOutput:(AVCaptureOutput *)captureOutput didOutputMetadataObjects:(NSArray *)metadataObjects fromConnection:(AVCaptureConnection *)connection{

        if (metadataObjects.count>0) {

            //[session stopRunning];

            AVMetadataMachineReadableCodeObject * metadataObject = [metadataObjects objectAtIndex : 0 ];

            //输出扫描字符串

            NSLog(@"result:%@",metadataObject.stringValue);

            [self dismissViewControllerAnimated:YES completion:^{

                self.getSysString(metadataObject.stringValue);

            }];

        }

    }

    进入这个界面之前的页面获得扫一扫的数据

    pushScan.getSysString = ^(NSString *str){

            startConnectStr = str;

            if (str) {

                //str 就是得到的数据

    //这里可以在扫一扫之后得到数据做点需要干的

            }

        };

    全文完毕,谢谢查看.

      

  • 相关阅读:
    软件测试课堂练习
    JSP第一次作业
    安卓第六次作业
    安卓第五次作业
    第四次安卓作业
    JSP第四周
    软件测试课堂练习3.4
    Android数据库表
    Android购物菜单
    Android增删改查
  • 原文地址:https://www.cnblogs.com/godlovexq/p/5663433.html
Copyright © 2020-2023  润新知