title: iOS二維碼操做
date: 2016-05-11 16:51:31ios
功能:掃描二維碼、條形碼,生成二維碼。具體使用請看項目。github地址 喜歡的朋友們給個星星吧。萌萌噠。git
添加二維碼界面github
假如你須要在項目中須要使用生成二維碼的功能,僅僅須要引入頭文件和建立二維碼視圖並添加就能夠了。例如這樣:session
#import "XYLScaningCode.h" @interface ViewController () @property(strong, nonatomic)XYLBinaryCodeView *binaryCodeView; //二維碼界面 @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; self.view.backgroundColor = [UIColor blackColor]; //設置生成二維碼界面 self.binaryCodeView = [[XYLBinaryCodeView alloc]initWithFrame:[UIScreen mainScreen].bounds]; //設置二維碼的內容 self.binaryCodeView.inputData = @"www.baidu.com"; [self.view insertSubview:self.binaryCodeView atIndex:1]; }
添加掃描二維碼、條形碼功能框架
假如你須要使用掃碼的功能,那代碼稍微多一點點,多的部分就是開始掃碼、讀取掃碼結果、處理掃碼結果那部分。ide
一樣的,你也須要引入上面的頭文件;atom
而後就是一些邏輯了,不用太擔憂,由於我會有不少的註釋,並且後面還會詳細分析。代碼以下:spa
#import "ViewController.h" #import "XYLScaningCode.h" @interface ViewController ()<UIAlertViewDelegate, AVCaptureMetadataOutputObjectsDelegate, XYLScanViewDelegate, UIImagePickerControllerDelegate, UINavigationControllerDelegate> { AVCaptureDevice *frontCamera; //前置攝像機 AVCaptureDevice *backCamera; //後置攝像機 AVCaptureSession *session; //捕捉對象 AVCaptureVideoPreviewLayer *previewLayer; AVCaptureInput *input; //輸入流 AVCaptureMetadataOutput *output;//輸出流 BOOL isTorchOn; } @property (nonatomic, assign) XYLScaningWarningTone tone; @property (nonatomic, strong) XYLScanView *overView; //掃碼界面 @property(strong, nonatomic)XYLBinaryCodeView *binaryCodeView; //二維碼界面 @property(weak, nonatomic)XYLToolButton *scanButton; @property(weak, nonatomic)XYLToolButton *payCodeButton; @property(weak, nonatomic)UILabel *titleLabel; @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; self.view.backgroundColor = [UIColor blackColor]; [self scanSelected]; } //點擊掃碼 -(void)scanSelected { if (![self.overView isDisplayedInScreen]) { #if TARGET_IPHONE_SIMULATOR UIAlertController *simulatorAlert = [UIAlertController alertControllerWithTitle:nil message:@"虛擬機不支持相機" preferredStyle:UIAlertControllerStyleActionSheet]; [simulatorAlert addAction:[UIAlertAction actionWithTitle:@"好吧" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) { return; }]]; [self presentViewController:simulatorAlert animated:YES completion:nil]; #elif TARGET_OS_IPHONE //判斷相機權限 [self isVideoUseable]; self.binaryCodeView.hidden = YES; if (self.overView) { self.overView.hidden = NO; }else{ //添加掃面界面視圖 [self initOverView]; [self initCapture]; [self config]; [self initUI]; [self addGesture]; } #endif } } -(void)isVideoUseable { AVAuthorizationStatus authStatus = [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo]; if (authStatus == AVAuthorizationStatusRestricted || authStatus == AVAuthorizationStatusDenied) { UIAlertController *simulatorAlert = [UIAlertController alertControllerWithTitle:nil message:@"相機權限未開通,請打開" preferredStyle:UIAlertControllerStyleActionSheet]; [simulatorAlert addAction:[UIAlertAction actionWithTitle:@"好吧" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) { return; }]]; [self presentViewController:simulatorAlert animated:YES completion:nil]; } }
/** * 添加掃碼視圖 */ - (void)initOverView { if (!_overView) { _overView = [[XYLScanView alloc]initWithFrame:[UIScreen mainScreen].bounds lineMode:XYLScaningLineModeDeafult ineMoveMode:XYLScaningLineMoveModeUpAndDown]; _overView.delegate = self; [self.view insertSubview:_overView atIndex:1]; } } //設置掃描反饋模式:這裏是聲音提示 - (void)config{ _tone = XYLScaningWarningToneSound; }
- (void)initCapture { //建立捕捉會話 session = [[AVCaptureSession alloc]init]; //高質量採集率 [session setSessionPreset:AVCaptureSessionPresetHigh]; //獲取攝像設備 NSArray *devices = [AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo]; for (AVCaptureDevice *camera in devices) { if (camera.position == AVCaptureDevicePositionFront) { frontCamera = camera; }else{ backCamera = camera; } } //建立輸入流 input = [AVCaptureDeviceInput deviceInputWithDevice:backCamera error:nil]; //輸出流 output = [[AVCaptureMetadataOutput alloc]init]; //設置代理 在主線程裏刷新 [output setMetadataObjectsDelegate:self queue:dispatch_get_main_queue()]; //添加輸入設備(數據從攝像頭輸入) if ([session canAddInput:input]) { [session addInput:input]; } //添加輸出數據 if ([session canAddOutput:output]) { [session addOutput:output]; } //設置設置輸入元數據的類型(以下設置條形碼和二維碼兼容) output.metadataObjectTypes = @[AVMetadataObjectTypeEAN13Code, AVMetadataObjectTypeEAN8Code, AVMetadataObjectTypeCode128Code, AVMetadataObjectTypeQRCode]; //添加掃描圖層 previewLayer = [AVCaptureVideoPreviewLayer layerWithSession:session]; previewLayer.videoGravity = AVLayerVideoGravityResizeAspectFill; previewLayer.frame = self.view.layer.bounds; [self.view.layer insertSublayer:previewLayer atIndex:0]; //開始捕獲 [session startRunning]; CGFloat screenHeight = ScreenSize.height; CGFloat screenWidth = ScreenSize.width; CGRect cropRect = CGRectMake((screenWidth - TransparentArea([_overView width], [_overView height]).width) / 2, (screenHeight - TransparentArea([_overView width], [_overView height]).height) / 2, TransparentArea([_overView width], [_overView height]).width, TransparentArea([_overView width], [_overView height]).height); //設置掃描區域 [output setRectOfInterest:CGRectMake(cropRect.origin.y / screenHeight, cropRect.origin.x / screenWidth, cropRect.size.height / screenHeight, cropRect.size.width / screenWidth)]; }
/** * 獲取掃描數據 */ - (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputMetadataObjects:(NSArray *)metadataObjects fromConnection:(AVCaptureConnection *)connection { NSString *stringValue; if (metadataObjects.count > 0) { AVMetadataMachineReadableCodeObject *metadateObject = [metadataObjects objectAtIndex:0]; stringValue = metadateObject.stringValue; [self readingFinshedWithMessage:stringValue]; [previewLayer removeFromSuperlayer]; } } /** * 讀取掃描結果 */ - (void)readingFinshedWithMessage:(NSString *)msg { if (msg) { [session stopRunning]; [self playSystemSoundWithStyle:_tone]; [self.overView stopMove]; UIAlertController *alert = [UIAlertController alertControllerWithTitle:nil message:msg preferredStyle:UIAlertControllerStyleActionSheet]; [alert addAction:[UIAlertAction actionWithTitle:@"肯定" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) { NSLog(@"掃描出來結果%@",msg); //todo:在這裏添加掃描結果後的處理 [self.overView removeFromSuperview]; self.overView = nil; [self payCodeSelected]; }]]; [self presentViewController:alert animated:YES completion:nil]; }else { UIAlertController *alert = [UIAlertController alertControllerWithTitle:nil message:@"讀取失敗" preferredStyle:UIAlertControllerStyleActionSheet]; [alert addAction:[UIAlertAction actionWithTitle:@"肯定" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) { NSLog(@"點擊了肯定"); }]]; [self presentViewController:alert animated:true completion:nil]; } }
/** * 展現聲音提示 */ - (void)playSystemSoundWithStyle:(XYLScaningWarningTone)tone{ NSString *path = [NSString stringWithFormat:@"%@/scan.wav", [[NSBundle mainBundle] resourcePath]]; SystemSoundID soundID; NSURL *filePath = [NSURL fileURLWithPath:path isDirectory:NO]; AudioServicesCreateSystemSoundID((__bridge CFURLRef)(filePath), &soundID); switch (tone) { case XYLScaningWarningToneSound: AudioServicesPlaySystemSound(soundID); break; case XYLScaningWarningToneVibrate: AudioServicesPlaySystemSound(kSystemSoundID_Vibrate); break; case XYLScaningWarningToneSoundAndVibrate: AudioServicesPlaySystemSound(soundID); AudioServicesPlaySystemSound(kSystemSoundID_Vibrate); break; default: break; } }
說明線程
你可能看到了,添加掃碼功能的時候,要遵循更多的協議,這是由於這裏使用了AVFoundation框架Apple原生掃描二維碼的一些功能,只須要遵循這些協議就能夠調用裏面的功能了。例如這裏的獲取掃碼結果的方法代理
/** * 獲取掃描數據 */ - (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputMetadataObjects:(NSArray *)metadataObjects fromConnection:(AVCaptureConnection *)connection;
而其他的,這裏詳細的註釋就能夠幫助你理解這些代碼了,若是想深刻了解具體實現過程,建議能夠看一下源碼github地址。