iOS 中二維碼掃描,ios掃描
隨著的大量推廣,越來越多的人會在生活中用到二維碼這一個方便大家的功能。
因此,很多的app中也逐漸的都加入了二維碼這個元素,今天先給大家介紹一下iOS7後系統內建自己可以手動設計的二維碼掃描。
QRCodeViewController這個類是實現二維碼掃描建立的類,今天我寫的這個類似於官方文檔中的實現,可以直接掃描二維碼跳轉到當前二維碼對應的連結,如果是應用的話,會跳轉到appStore中對應的應用詳情。
除了這個,現在用的比較多的還有ZBarSDK等三方庫,實現的效果要比自己寫的這個漂亮,後面有機會的話,我會介紹一下ZBarSDK的用法以及經常遇到的問題和解決方案。
下面是主要實現:
#import "QRCodeViewController.h"
#import <AVFoundation/AVFoundation.h>
@interface QRCodeViewController () <AVCaptureMetadataOutputObjectsDelegate>
{
BOOL _isReading;
}
@property (weak, nonatomic) IBOutlet UIView *ShowView;
@property (nonatomic,strong) UIView *boxView;
//@property (nonatomic,assign) BOOL *isReading;
@property (nonatomic,strong) CALayer *scanLayer;
@property (nonatomic,strong) UILabel *urlLabel;
-(BOOL)startReading;
-(void)stopReading;
//捕捉會話
@property (nonatomic,strong) AVCaptureSession *captureSession;
//展示layer
@property (nonatomic,strong) AVCaptureVideoPreviewLayer *videoPreviewLayer;
@end
@implementation QRCodeViewController
- (void)viewDidLoad {
[super viewDidLoad];
UIButton *btn = [UIButton buttonWithType:UIButtonTypeSystem];
btn.frame = CGRectMake(0, 30, 50, 30);
[btn setImage:[UIImage imageNamed:@"return@2x"] forState:UIControlStateNormal];
[btn addTarget:self action:@selector(leftClicked) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:btn];
_captureSession = nil;
//_isReading = NO;
[self startReading];
}
-(void)leftClicked{
[self dismissViewControllerAnimated:YES completion:nil];
}
-(BOOL)startReading{
NSError *error = nil;
//1.初始化捕捉裝置(AVCaptureDevice),類型為AVMediaTypeVideo
AVCaptureDevice *captureDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
//2.用captureDevice建立輸入資料流
AVCaptureDeviceInput *input = [AVCaptureDeviceInput deviceInputWithDevice:captureDevice error:&error];
if (!input) {
NSLog(@"%@",[error localizedDescription]);
return NO;
}
//3.建立媒體資料輸出資料流
AVCaptureMetadataOutput *captureMedataOutput = [[AVCaptureMetadataOutput alloc]init];
//4.執行個體化捕捉會話
_captureSession = [[AVCaptureSession alloc]init];
//4.1將輸入資料流添加到會話
[_captureSession addInput:input];
//4.2將媒體輸出資料流添加到會話中
[_captureSession addOutput:captureMedataOutput];
//5.建立串列隊列,並將媒體輸出資料流添加到隊列中
dispatch_queue_t dispatchQueue;
dispatchQueue = dispatch_queue_create("myQueue", NULL);
//5.1設定代理
[captureMedataOutput setMetadataObjectsDelegate:self queue:dispatchQueue];
//5.2設定輸出媒體資料類型為QRCode
[captureMedataOutput setMetadataObjectTypes:[NSArray arrayWithObject:AVMetadataObjectTypeQRCode]];
//6.執行個體化預覽圖層
_videoPreviewLayer = [[AVCaptureVideoPreviewLayer alloc]initWithSession:_captureSession];
//7.設定預覽圖層填充方式
[_videoPreviewLayer setVideoGravity:AVLayerVideoGravityResizeAspectFill];
//8.設定圖層的frame
[_videoPreviewLayer setFrame:_ShowView.layer.bounds];
//9.將圖層添加到預覽view的圖層上
[_ShowView.layer addSublayer:_videoPreviewLayer];
//10.設定掃描範圍
captureMedataOutput.rectOfInterest = CGRectMake(0.2f, 0.2f, 0.8f, 0.8f);
//10.1. 設定掃描框
_boxView = [[UIView alloc]initWithFrame:CGRectMake(_ShowView.bounds.size.width * 0, _ShowView.bounds.size.height*0, _ShowView.bounds.size.width, _ShowView.bounds.size.height)];
_boxView.layer.borderColor = [UIColor greenColor].CGColor;
_boxView.layer.borderWidth = 1.0f;
[_ShowView addSubview:_boxView];
//10.2掃描線
_scanLayer = [[CALayer alloc]init];
_scanLayer.frame = CGRectMake(0, 0, _boxView.bounds.size.width, 2);
_scanLayer.backgroundColor = [UIColor cyanColor].CGColor;
[_boxView.layer addSublayer:_scanLayer];
NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:0.2f target:self selector:@selector(moveScanLayer:) userInfo:nil repeats:YES];
[timer fire];
//11.開始掃描
[_captureSession startRunning];
return 1;
}
-(void)moveScanLayer:(NSTimer *)timer{
CGRect frame = _scanLayer.frame;
if (_boxView.frame.size.height <= _scanLayer.frame.origin.y) {
frame.origin.y = 0;
_scanLayer.frame = frame;
}
else{
frame.origin.y += 5;
[UIView animateWithDuration:0.1 animations:^{
_scanLayer.frame = frame;
}];
}
}
-(void)stopReading{
// [_captureSession stopRunning];
// _captureSession = nil;
// [_scanLayer removeFromSuperlayer];
// [_videoPreviewLayer removeFromSuperlayer];
}
#pragma mark - AVCaptureMetadataOutputObjectsDelegate
-(void)captureOutput:(AVCaptureOutput *)captureOutput didOutputMetadataObjects:(NSArray *)metadataObjects fromConnection:(AVCaptureConnection *)connection{
//判斷是否有資料
if (metadataObjects !=nil && [metadataObjects count]>0) {
AVMetadataMachineReadableCodeObject *metadataObj = [metadataObjects objectAtIndex:0];
//判斷回傳的資料類型
if ([[metadataObj type] isEqualToString:AVMetadataObjectTypeQRCode]) {
[self performSelectorOnMainThread:@selector(setUrl:) withObject:[metadataObj stringValue] waitUntilDone:NO];
//[[UIApplication sharedApplication] openURL:url];
[self performSelectorOnMainThread:@selector(stopReading) withObject:nil waitUntilDone:NO];
_isReading = NO;
}
}
}
-(void)setUrl:(NSString *)text{
NSURL *url = [NSURL URLWithString:text];
[[UIApplication sharedApplication] openURL:url];
}