早前面試的時候被問到掃描使用的是什么 脫口而出用的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 就是得到的數據
//這里可以在掃一掃之后得到數據做點需要干的
}
};
全文完畢,謝謝查看.
