最近在做掃描二維碼相關功能,網上關於這方面的介紹比較少,就稍微總結了一下,希望對大家有所幫助;
1.使用系統的AVFoundation做的二維碼掃描器(iOS7以後),這方面的代碼還是比較多的,以下是借鑑的代碼。具體代碼,參照:http://www.jianshu.com/p/6b7d54b3f88b
-(void)setupCamera {
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
// 耗時的操作
// Device
_device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
// Input
_input = [AVCaptureDeviceInput deviceInputWithDevice:self.device error:nil];
// Output
_output = [[AVCaptureMetadataOutput alloc]init];
// [_output setMetadataObjectsDelegate:self queue:dispatch_get_main_queue()];
[ _output setRectOfInterest : CGRectMake ((60+64)/SCREEN_HEIGHT ,40/SCREEN_WIDTH , SCAN_HEIGHT/SCREEN_HEIGHT , SCAN_HEIGHT/SCREEN_WIDTH )];//限制掃描區域
[_output setMetadataObjectsDelegate:self queue:dispatch_get_main_queue()];
// Session
_session = [[AVCaptureSession alloc]init];
[_session setSessionPreset:AVCaptureSessionPresetHigh];
if ([_session canAddInput:self.input])
{
[_session addInput:self.input];
}
if ([_session canAddOutput:self.output])
{
[_session addOutput:self.output];
}
// 條碼類型 AVMetadataObjectTypeQRCode
_output.metadataObjectTypes =@[AVMetadataObjectTypeQRCode];
dispatch_async(dispatch_get_main_queue(), ^{
// 更新界面
// Preview
_preview =[AVCaptureVideoPreviewLayer layerWithSession:self.session];
_preview.videoGravity = AVLayerVideoGravityResizeAspectFill;
// _preview.frame =CGRectMake(20,110,280,280);
_preview.frame = self.view.bounds;
[self.view.layer insertSublayer:self.preview atIndex:0];
// Start
[_session startRunning];
});
});
}
注:關於掃描範圍,可參照http://www.2cto.com/kf/201411/356046.html,該作者有關於這部分的詳細解釋。
2.添加黑色透明背景,中間透明區域,用於掃描,主要思想是添加一個黑色半透明view,使用CGContextClearRect方法,將掃描範圍的正方形區域擦除。相關代碼如下:
-(void) drawViewForScan {
ScanView* bgView = [[ScanView alloc] initWithFrame:CGRectMake(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT)];
[self.view addSubview:bgView ];
//掃描區域
UIView* scanView = [[UIView alloc] initWithFrame:CGRectMake (40 , 60 + 64 ,SCAN_HEIGHT, SCAN_HEIGHT )];
scanView.backgroundColor = [UIColor clearColor];
[scanView.layer setMasksToBounds:YES];
[scanView.layer setBorderWidth:0.5];
scanView.layer.borderColor = [UIColor whiteColor].CGColor;
[self.view addSubview:scanView];
float width = 8.0f;
float height = 2.0f;
//左上角邊框樣式
UIView* LeftTopView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, width+height, height)];
LeftTopView.backgroundColor = [UIColor greenColor];
[scanView addSubview:LeftTopView];
UIView* LeftTopView2 = [[UIView alloc] initWithFrame:CGRectMake(0, height, height, width)];
LeftTopView2.backgroundColor = [UIColor greenColor];
[scanView addSubview:LeftTopView2];
//右上角邊框樣式
UIView* RightTopView = [[UIView alloc] initWithFrame:CGRectMake(SCAN_HEIGHT-width-height, 0, width+height, height)];
RightTopView.backgroundColor = [UIColor greenColor];
[scanView addSubview:RightTopView];
UIView* RightTopView2 = [[UIView alloc] initWithFrame:CGRectMake(SCAN_HEIGHT-height, height, height, width)];
RightTopView2.backgroundColor = [UIColor greenColor];
[scanView addSubview:RightTopView2];
//左下角邊框樣式
UIView* LeftLowView = [[UIView alloc] initWithFrame:CGRectMake(0, SCAN_HEIGHT-width-height, height, width)];
LeftLowView.backgroundColor = [UIColor greenColor];
[scanView addSubview:LeftLowView];
UIView* LeftLowView2 = [[UIView alloc] initWithFrame:CGRectMake(0, SCAN_HEIGHT-height, height+width, height)];
LeftLowView2.backgroundColor = [UIColor greenColor];
[scanView addSubview:LeftLowView2];
//右下角邊框樣式
UIView* RightLowView = [[UIView alloc] initWithFrame:CGRectMake(SCAN_HEIGHT-height, SCAN_HEIGHT-width-height, height, width)];
RightLowView.backgroundColor = [UIColor greenColor];
[scanView addSubview:RightLowView];
UIView* RightLowView2 = [[UIView alloc] initWithFrame:CGRectMake(SCAN_HEIGHT-height-width, SCAN_HEIGHT-height, width+height, height)];
RightLowView2.backgroundColor = [UIColor greenColor];
[scanView addSubview:RightLowView2];
_line = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"line.png"]];
_line.frame = CGRectMake(0, 0, SCAN_HEIGHT, 2);
[scanView addSubview:_line];
}
CGContextClearRect方法在ScanView(黑色背景View,繼承一個UIView就可以)的- (void)drawRect:(CGRect)rect方法裏,相關代碼如下:
- (void)drawRect:(CGRect)rect {
CGContextRef context = UIGraphicsGetCurrentContext();
CGRect drawRect = CGRectMake (40 , 60 + 64 , SCREEN_WIDTH-80 , SCREEN_WIDTH-80 );
CGContextClearRect(context, drawRect); //clear the center rect of the layer
}
- (id)initWithFrame:(CGRect)frame {
if (self = [super initWithFrame:frame]) { //2
self.backgroundColor = [UIColor colorWithRed:0.0/255.0 green:0.0/255.0 blue:0.0/255.0 alpha:0.5];
UILabel * labIntroudction= [[UILabel alloc] initWithFrame:CGRectMake(50, 60+64+SCAN_HEIGHT, SCAN_HEIGHT-10, 20)];
labIntroudction.backgroundColor = [UIColor clearColor];
//labIntroudction.numberOfLines=2;
labIntroudction.font = [UIFont systemFontOfSize:14.0f];
labIntroudction.textColor=[UIColor whiteColor];
labIntroudction.text=@"將二維碼/條碼放入框內,即可自動掃描";
[labIntroudction sizeToFit];
labIntroudction.center = CGPointMake(self.bounds.size.width/2,60+64+SCAN_HEIGHT+15);
[self addSubview:labIntroudction];
}
return self;
}
注:關於掃描區域的樣式,即四個角都有綠色邊角,也可以使用UIImageView,採用圖片即可。
3.添加掃描動畫效果,相關代碼如下:
在- (void)viewDidLoad添加定時器初始化部分的代碼,如下:
upOrdown = NO;
num =0;
timer = [NSTimer scheduledTimerWithTimeInterval:.02 target:self selector:@selector(animation1) userInfo:nil repeats:YES];
定時器動畫代碼:
-(void)animation1 {
if (upOrdown == NO) {
num++;
_line.frame = CGRectMake(0, num, SCAN_HEIGHT, 2);
if (num == SCAN_HEIGHT) {
num=0;
}
}
}
4.掃描成功事件響應,處理掃描結果。
#pragma mark AVCaptureMetadataOutputObjectsDelegate
- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputMetadataObjects:(NSArray *)metadataObjects fromConnection:(AVCaptureConnection *)connection {
NSString *stringValue;
if ([metadataObjects count] >0) {
AVMetadataMachineReadableCodeObject * metadataObject = [metadataObjects objectAtIndex:0];
stringValue = metadataObject.stringValue;//掃描最終結果
}
[_session stopRunning];
[timer invalidate];
[self joinOrg:stringValue];//連接api方法
}
以上就是相關步驟以及代碼,因爲網上實在相關代碼太少,儘管我寫的不是太好,也希望幫到別人,由於經驗不足,可能有的地方寫的不到位,希望指正。