IOS二维码(ZXingObjc)

IOS二维码(ZXingObjc)

前言


公司最近上线一款产品,是通过二维码扫描登录。开发阶段的时候使用的是IOS原生的AVFoundation框架。但是生产线做出的二维码却意外的扫不出来。最终是换用ZXingObjC才解决问题。

IOS二维码(ZXingObjc)_第1张图片
原生的能扫出来么?

ZXingObjC


ZXing是一个开放源码的,用Java实现的多种格式的1D/2D条码图像处理库,目前由Google维护更新。ZXingObjC是ZXing的objective-c版本库,在许多IOS开发项目中使用。

下载安装

  • cocoapods: pod 'ZXingObjC', '~> 3.2.1' (速度很慢,有的时候下载失败)
  • gitHub 下载:地址
  • 我在demo中使用的源代码:百度云盘

依赖库和编译

ZXingObjC在IOS中主要依赖以下框架:

  • AVFoundation.framework
  • CoreGraphics.framework
  • CoreMedia.framework
  • CoreVideo.framework
  • Foundation.framework
  • ImageIO.framework
  • QuartzCore.framework
  • UIKit.framework

将上述框架添加到项目中就能正常编译。

设置相册访问描述


添加相册访问

ZXCaptureDelegate

ZXing的使用很简单,生成ZXCapture捕获器,然后将ZXCapture的layer.frame设成控制器view的大小,然后将ZXCapture的layer添加到view的layer上,最后设置delegate就完成了配置。当摄像头扫描到二维码或者条形码的时候,就会调用- (void)captureResult:(ZXCapture *)capture result:(ZXResult *)result方法,参考代码如下:

- (void)setupCapture{
    self.capture = [[ZXCapture alloc]init];
    self.capture.camera = self.capture.back;
    //自动聚焦
    self.capture.focusMode =    AVCaptureFocusModeContinuousAutoFocus;
    self.capture.layer.frame = CGRectMake(0, 64,    SCREEN_WIDTH, SCREEN_HEIGHT - 64);
      [self.view.layer addSublayer:self.capture.layer];
    [self.view bringSubviewToFront:self.scanSuperView];
    for (UIView * view in _blackBackgroundViewsArray) {
        [self.view bringSubviewToFront:view];
    }
    self.capture.delegate = self;

    //设置扫描区域
    xxxxx
  }
  
  
    #pragma mark - ZXCaptureDelegate
- (void)captureResult:(ZXCapture *)capture result:(ZXResult *)result {
    if (!result) return;
    NSLog(@"\n%@\n",result.text);

    if (result.barcodeFormat == kBarcodeFormatQRCode) {
    AudioServicesPlaySystemSound(kSystemSoundID_Vibrate);

        [self.capture stop];
        [[[UIAlertView alloc]initWithTitle:@"结果" message: result.text delegate:self cancelButtonTitle:@"好的" otherButtonTitles: nil] show];
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 2 * NSEC_PER_SEC), dispatch_get_main_queue(), ^{
                    [self.capture start];
                });
    }
}

关于旋转

捕获器默认的获取精度是1280*720,但是它是横屏的,如果要竖屏扫描就必须旋转下。下面是旋转代码。

 //旋转
    UIInterfaceOrientation orientation = [[UIApplication sharedApplication] statusBarOrientation];
    float scanRectRotation;
    float captureRotation;

    switch (orientation) {
         case UIInterfaceOrientationPortrait:
            captureRotation = 0;
            scanRectRotation = 90;
            break;
         case UIInterfaceOrientationLandscapeLeft:
         captureRotation = 90;
         scanRectRotation = 180;
         break;
         case UIInterfaceOrientationLandscapeRight:
            captureRotation = 270;
            scanRectRotation = 0;
            break;
         case UIInterfaceOrientationPortraitUpsideDown:
            captureRotation = 180;
            scanRectRotation = 270;
            break;
         default:
            captureRotation = 0;
            scanRectRotation = 90;
            break;
    }
    CGAffineTransform transform = CGAffineTransformMakeRotation((CGFloat) (captureRotation / 180 * M_PI));
    [self.capture setTransform:transform];
    [self.capture setRotation:scanRectRotation];

关于扫描区域(scanRect)的计算(重点)

ZXing的scanRect的设置网上有很多错误说法,有的直接贴上复杂的代码,然而没有一个很好的解释scanRect的数据是怎么来的。下面我就举一个例子,假设capture.sessionPreset设置的是AVCaptureSessionPreset1280x720(如果没设默认是1280*720),要将其投射到一个iPad上,如图蓝色所示,中间绿色的部分是我们想要的扫描区域。这时候,capture.scanRect并不是scanView1.frame 而是 scanView2.frame。因此我们要做一道数学题,将scanView2.frame通过scanView1.frame等比例缩放计算出来。

IOS二维码(ZXingObjc)_第2张图片
计算扫描区域

首先是计算缩放比例:

图中例子中,长方形缩放到正方形屏幕,肯定有一部分多出来,因此长宽比不可能相同,到底是用scanView1.width / scanView2.width 还是 scanView1.height / scanView2.height 作为缩放比例呢?通过简单计算得出结论(可以自己举例子试下):

  • scale = max(scanView1.width / scanView2.width , scanView1.height / scanView2.height)

比例确定下来了,长和宽就很好计算了

  • height = scanView1.height / scale

  • width = scanView1.width / scale

到这里需要注意下x和y的计算,如果多出来的是height,那么x就能按比例计算,y通过x与y的比例计算。如果多出来的是width,那么y久能按比例算出来,x通过x与y的比例计算。

if (scanView1.width / scanView2.width > scanView1.height / scanView2.height){
x = scanView1.x / scale;
y = x * scanView1.y / scanView1.x;

}
else {
y = scanView1.y / scale;
x = y * scanView1.x / scanView1.y;
}

最后就可以得到scanRect

  • scanRect = CGRectmake(x,y,width,height)

demo下载


  • 百度云盘:下载地址

你可能感兴趣的:(IOS二维码(ZXingObjc))