前言
早上使用微信的時(shí)候豺瘤,突然想到以前在項(xiàng)目中集成掃碼功能吆倦,當(dāng)時(shí)沒有從相冊(cè)中掃描二維碼的需求,加上需要向下兼容坐求,于是選擇集成了zbar掃描蚕泽。今天我們就來看一下如何實(shí)現(xiàn)從相冊(cè)中掃碼、以及原生掃描。
原生掃描
iOS7之后须妻,AVFoundation讓我們終于可以使用原生掃描進(jìn)行掃碼了(二維碼與條碼皆可)AVFoundation可以讓我們從設(shè)備中獲取到輸入流與輸出流仔蝌,從而獲取二維碼中包含的信息。
實(shí)現(xiàn)原生掃描非常簡(jiǎn)單荒吏。
1.先導(dǎo)入AVFoundation框架敛惊。
<AVFoundation/AVFoundation.h>
2.接著設(shè)置代理,實(shí)現(xiàn)代理回調(diào)方法
AVCaptureMetadataOutputObjectsDelegate
3.然后創(chuàng)建幾個(gè)類即可:
設(shè)備 AVCaptureDevice
捕捉會(huì)話 AVCaptureSession
輸入流 AVCaptureDeviceInput
輸出流 AVCaptureMetadataOutput
預(yù)覽圖層 AVCaptureVideoPreviewLayer下面是簡(jiǎn)單的代碼實(shí)現(xiàn)示例
NSError *error = nil;
AVCaptureDevice *captureDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];//設(shè)備
AVCaptureSession *session = [[AVCaptureSession alloc] init];//捕捉會(huì)話
[session setSessionPreset:AVCaptureSessionPresetHigh];//設(shè)置采集率
AVCaptureDeviceInput *input = [AVCaptureDeviceInput deviceInputWithDevice:captureDevice error:&error];//輸入流
AVCaptureMetadataOutput *output = [[AVCaptureMetadataOutput alloc] init];//輸出流
//添加到捕捉會(huì)話
[session addInput:input];
[session addOutput:output];
//掃碼類型:需要先將輸出流添加到捕捉會(huì)話后再進(jìn)行設(shè)置
//這里只設(shè)置了可掃描二維碼,有條碼需要绰更,在數(shù)組中繼續(xù)添加即可
[output setMetadataObjectTypes:@[AVMetadataObjectTypeQRCode]];
//輸出流delegate,在主線程刷新UI
[output setMetadataObjectsDelegate:self queue:dispatch_get_main_queue()];
AVCaptureVideoPreviewLayer *videoPreviewLayer = [[AVCaptureVideoPreviewLayer alloc] initWithSession:session];//預(yù)覽
videoPreviewLayer.frame = self.view.bounds;
[self.view.layer insertSublayer:videoPreviewLayer atIndex:0];//添加預(yù)覽圖層
//還可以設(shè)置掃描范圍 output.rectOfInterest 不設(shè)置默認(rèn)為全屏
//開始掃描
[session startRunning];```
* 接著實(shí)現(xiàn)掃碼成功的回調(diào)方法
- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputMetadataObjects:(NSArray *)metadataObjects fromConnection:(AVCaptureConnection *)connection {
NSString *content = @"";
AVMetadataMachineReadableCodeObject *metadataObject = metadataObjects.firstObject;
content = metadataObject.stringValue;//獲取到二維碼中的信息字符串
//對(duì)此字符串進(jìn)行處理(音效瞧挤、網(wǎng)址分析、頁(yè)面跳轉(zhuǎn)等)
}```
- 我們還可以添加掃碼成功后的聲音與振動(dòng)效果儡湾,提高用戶體驗(yàn)
- (void)playBeep{
SystemSoundID soundID;
AudioServicesCreateSystemSoundID((__bridge CFURLRef)[NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:@"滴-2"ofType:@"mp3"]], &soundID);
AudioServicesPlaySystemSound(soundID);
AudioServicesPlaySystemSound(kSystemSoundID_Vibrate);
}
從相冊(cè)獲取二維碼
- iOS8之后特恬,可以使用CIDetector(CIDetector可用于人臉識(shí)別)進(jìn)行圖片解析,從而使我們可以便捷的從相冊(cè)中獲取到二維碼徐钠。
- 1.調(diào)用系統(tǒng)相冊(cè)癌刽,從系統(tǒng)相冊(cè)中選取圖片
2.使用探測(cè)器(CIDetector)對(duì)選取的圖片進(jìn)行處理,取得圖片二維碼中包含的數(shù)據(jù)信息尝丐。 - 下面是簡(jiǎn)單的代碼實(shí)現(xiàn)示例
- (void)choicePhoto{
//調(diào)用相冊(cè)
UIImagePickerController *imagePicker = [[UIImagePickerController alloc]init];
imagePicker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
imagePicker.delegate = self;
[self presentViewController:imagePicker animated:YES completion:nil];
}
//選中圖片的回調(diào)
-(void)imagePickerController:(UIImagePickerController*)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{
NSString *content = @"" ;
//取出選中的圖片
UIImage *pickImage = info[UIImagePickerControllerOriginalImage];
NSData *imageData = UIImagePNGRepresentation(pickImage);
CIImage *ciImage = [CIImage imageWithData:imageData];
//創(chuàng)建探測(cè)器
CIDetector *detector = [CIDetector detectorOfType:CIDetectorTypeQRCode context:nil options:@{CIDetectorAccuracy: CIDetectorAccuracyLow}];
NSArray *feature = [detector featuresInImage:ciImage];
//取出探測(cè)到的數(shù)據(jù)
for (CIQRCodeFeature *result in feature) {
content = result.messageString;
}
//進(jìn)行處理(音效妒穴、網(wǎng)址分析、頁(yè)面跳轉(zhuǎn)等)
}
源碼
點(diǎn)此下載:github源碼
結(jié)語(yǔ)
原生掃描比zbar摊崭、zxing效率更高讼油,且這兩個(gè)庫(kù)年久失修(zxingOBJC有人在持續(xù)維護(hù))還有兼容性問題。
CIDetector是系統(tǒng)為我們提供的非常強(qiáng)大的類庫(kù)呢簸,但是很多公司因?yàn)樾枰蛳录嫒莅ǎ詻]有辦法使用。
如果項(xiàng)目不需向下兼容多個(gè)版本時(shí)根时,建議使用系統(tǒng)原生掃描以及CIDetector進(jìn)行二維碼相關(guān)處理瘦赫。
參考:
http://www.tuicool.com/articles/ie2aAjv
http://www.reibang.com/p/cc79c45b4ccf