二维码扫描和创建(上)

WilMurray 8年前

来自: 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:^{      }];

还要实现 代理 :

- (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];      }

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;  }

在 -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];    }

实现 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;              }            }      }  }

iOS原生的扫码界面你可以随意的自定义了,和自定义相机一样,这里就不做介绍了。

扫描相册中的二维码

扫描相册中的二维码,首先打开相册然后先在UIImagePickerControllerDelegate代理方法中:

 #pragma mark - imagePickerController delegate  - (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info  {      //1.获取选择的图片      UIImage *image = info[UIImagePickerControllerOriginalImage];      //2.初始化一个监测器      CIDetector*detector = [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:@"该图片没有包含一个二维码!"];          }      }];  }

好了,关于扫描二维码今天就说到这,下一篇我会分享创建二维码功能。 扫描二维码和创建二维码项目展示:APPStore搜索 扫码神奇 。上一篇文章 http://www.lvesli.com/?p=412 中有扫码神奇的具体介绍:

关注微信公众号: lecoding 实时关注文章更新。你也可以扫描下方二维码关注我们:

</div>