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 就是得到的数据

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

        }

    };

全文完毕,谢谢查看.

  

 

posted @ 2016-07-12 14:31  ios攻城狮  阅读(5512)  评论(0编辑  收藏  举报