二維碼掃描和創建(上)

WilMurray 8年前發布 | 22K 次閱讀 iOS開發 移動開發

來自: 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 實時關注文章更新。你也可以掃描下方二維碼關注我們:

    </div>

 本文由用戶 WilMurray 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!