二維碼掃描和創建(上)
來自: http://www.lvesli.com/?p=421
掃描二維碼(包括讀取和解碼)
掃描二維碼 OC 的開源庫有 ZBar和ZXing 。 iOS7 以后iOS擁有原生的掃碼功能。
我在iPhone項目 掃碼神奇 中使用的就是下面第三種方法,大家可以到APPStore搜索 掃碼神奇 ,下載體驗一下(記得給個好評呦)。 掃碼神奇 下載鏈接: https://itunes.apple.com/cn/app/id1074173840
好了下面是具體實現介紹:
ZXing
現在 OC 版本已經停止維護,Java版本還在維護, github 鏈接: https://github.com/zxing/zxing ,現在也很少有人使用,在 唐巧 的一篇12年 http://blog.devtang.com/blog/2012/12/23/use-zxing-library/ 文章中有關于 ZXing的 配置過程,不過好像他好久沒有更新了。 ZXing 相對于 ZBar 的好處是讀取和掃碼速度快,但是整合到 Xcode 項目中比較痛苦。
ZBar
ZBar 的 github 地址: https://github.com/bmorton/ZBarSDK ,在github上下載的 .a 文件不支持 64位 ,好像也有好今年沒有更新了,不過我在網上找到了支持64位的 .a 文件,下載鏈接: https://markobl.com/2015/03/27/zbar-sdk-64-bit-for-iphone-6-and-ios-8-download/ ,下面說一下 ZBar 的集成步驟:
-
從 github 上下載源文件,解壓后如下圖,把Headers文件夾拖入到項目中。
-
從 64位.a文件 下載支持64位的.a文件,添加到項目中
-
在新工程中導入以下框架: AVFoundation.framework、CoreMedia.framework、CoreVideo.framework、QuartzCore.framework、libiconv.dylib
-
在需要使用的頁面 .h 文件中引用頭文件 #import "ZBarSDK.h"
.m 文件中在點擊開始掃描的按鈕中實現:
ZBarReaderViewController *reader = [ZBarReaderViewController new];
reader.readerDelegate = self;
reader.supportedOrientationsMask = ZBarOrientationMaskAll;ZBarImageScanner *scanner = reader.scanner;
[scanner setSymbology: ZBAR_I25
config: ZBAR_CFG_ENABLE
to: 0];
[self presentViewController:reader
animated:YES
completion:^{
}];</pre>還要實現 代理 :
- (void) imagePickerController: (UIImagePickerController) reader didFinishPickingMediaWithInfo: (NSDictionary) info{ id<NSFastEnumeration> results = [info objectForKey: ZBarReaderControllerResults];
ZBarSymbol symbol = nil;
for(symbol in results)
break;
[self dismissViewControllerAnimated:YES
completion:^{
}];
NSString code = [NSString stringWithString:symbol.data];}</pre>
ZBar 有一個弊端,因為他是靜態文件,所以自定義相機比較困難,只能進行簡單的修改,我嘗試實現微信掃碼效果沒有實現。
iOS原生掃碼
iOS7以后APPle有了自己原生的掃碼接口,我當然要義無反顧地選擇使用原生的了,下面是我在項目中的部分代碼: 在.m文件中:
#import <AVFoundation/AVFoundation.h> @interface SysScannerController ()<AVCaptureMetadataOutputObjectsDelegate,UIImagePickerControllerDelegate,UINavigationControllerDelegate> @property (nonatomic, strong) AVCaptureSession *session;//輸入輸出的中間橋梁 @property (strong,nonatomic)AVCaptureDevice *device; @property (strong,nonatomic)AVCaptureDeviceInput *input; @property (strong,nonatomic)AVCaptureMetadataOutput *output; @property (strong,nonatomic)AVCaptureVideoPreviewLayer *preview; @end懶加載:
#pragma mark - Setter & Getter -(UIView *)line{ if (_line == nil) { _line = [[UIView alloc] initWithFrame:CGRectMake((ScreenFrameWith-180)/2, ScreenFrameHeight/3.f, 180, 4)]; _line.backgroundColor=[UIColor whiteColor]; [self.view addSubview:_line]; } return _line; }-(AVCaptureDevice )device{ if (_device == nil) { _device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo]; } return _device; } -(AVCaptureDeviceInput )input{ if (_input == nil) { _input = [AVCaptureDeviceInput deviceInputWithDevice:self.device error:nil]; } return _input; } -(AVCaptureMetadataOutput *)output{ if (_output == nil) { _output = [[AVCaptureMetadataOutput alloc]init]; [_output setMetadataObjectsDelegate:self queue:dispatch_get_main_queue()]; //限制掃描區域(上左下右) [ _output setRectOfInterest : CGRectMake (1/6.f,1/6.f,4/6.f,4/6.f)]; } return _output; }
(AVCaptureSession *)session{ if (_session == nil) {
// 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]; }
} return _session; }
-(AVCaptureVideoPreviewLayer *)preview{ if (_preview == nil) { _preview =[AVCaptureVideoPreviewLayer layerWithSession:self.session];
}
return _preview;
}</pre>
在 -viewDidLoad 中調用下面函數:
- (void)setupCamera { //1. if(self.device == nil){ [self showAlertTipWithTitle:@"未檢測到相機" andMessage:@"請檢查相機設備是否正常"]; return ; } // 2.添加預覽圖層 [self.view.layer insertSublayer:self.preview atIndex:0]; self.preview.frame = self.view.bounds; // 3.設置輸出能夠解析的數據類型 // 注意點: 設置數據類型一定要在輸出對象添加到會話之后才能設置 self.output.metadataObjectTypes = self.output.availableMetadataObjectTypes; // 4.設置監聽監聽輸出解析到的數據 [self.output setMetadataObjectsDelegate:self queue:dispatch_get_main_queue()]; // 5.開始掃描 [self.session startRunning];}</pre>
實現 AVCaptureMetadataOutputObjectsDelegate 代理:
#pragma mark AVCaptureMetadataOutputObjectsDelegate
(void)captureOutput:(AVCaptureOutput )captureOutput didOutputMetadataObjects:(NSArray )metadataObjects fromConnection:(AVCaptureConnection *)connection {
if ([metadataObjects count] >0) {
AVMetadataMachineReadableCodeObject * metadataObject = [metadataObjects objectAtIndex:0]; if ([metadataObject isKindOfClass:[AVMetadataMachineReadableCodeObject class]]) { NSString *stringValue = [metadataObject stringValue]; if (stringValue != nil) { [self.session stopRunning]; //掃描結果 self.scannedResult=stringValue; } }
} }</pre>
iOS原生的掃碼界面你可以隨意的自定義了,和自定義相機一樣,這里就不做介紹了。
掃描相冊中的二維碼
掃描相冊中的二維碼,首先打開相冊然后先在UIImagePickerControllerDelegate代理方法中:
#pragma mark - imagePickerController delegate
(void)imagePickerController:(UIImagePickerController )picker didFinishPickingMediaWithInfo:(NSDictionary )info { //1.獲取選擇的圖片 UIImage image = info[UIImagePickerControllerOriginalImage]; //2.初始化一個監測器 CIDetectordetector = [CIDetector detectorOfType:CIDetectorTypeQRCode context:nil options:@{ CIDetectorAccuracy : CIDetectorAccuracyHigh }];
[picker dismissViewControllerAnimated:YES completion:^{
//監測到的結果數組 NSArray *features = [detector featuresInImage:[CIImage imageWithCGImage:image.CGImage]]; if (features.count >=1) { /**結果對象 */ CIQRCodeFeature *feature = [features objectAtIndex:0]; NSString *scannedResult = feature.messageString; self.scannedResult=scannedResult; [self performSegueWithIdentifier:@"ToResult" sender:self]; } else{ [self showAlertTipWithTitle:@"提示" andMessage:@"該圖片沒有包含一個二維碼!"]; }
}]; }</pre>
好了,關于掃描二維碼今天就說到這,下一篇我會分享創建二維碼功能。 掃描二維碼和創建二維碼項目展示:APPStore搜索 掃碼神奇 。上一篇文章 http://www.lvesli.com/?p=412 中有掃碼神奇的具體介紹:
關注微信公眾號: lecoding 實時關注文章更新。你也可以掃描下方二維碼關注我們: