二维码扫描和创建(上)

saomashengqi.png

##扫描二维码(包括读取和解码)

扫描二维码OC的开源库有ZBar和ZXingiOS7以后iOS拥有原生的扫码功能。
我在iPhone项目扫码神奇中使用的就是下面第三种方法,大家可以到APPStore搜索扫码神奇,下载体验一下(记得给个好评呦)。扫码神奇下载链接:
https://itunes.apple.com/cn/app/id1074173840

icon108.png

好了下面是具体实现介绍:

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

ZBargithub地址: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搜索扫码神奇(记得给个好评呦)。


更多精彩文章请关注微信公众账号:lecoding,你也可以扫描下方二维码关注我们。

icon