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 就是得到的數據

//這里可以在掃一掃之后得到數據做點需要干的

        }

    };

全文完畢,謝謝查看.

  

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM