早前面试的时候被问到扫描使用的是什么 脱口而出用的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 就是得到的数据
//这里可以在扫一扫之后得到数据做点需要干的
        }
    };

全文完毕,谢谢查看.