zoukankan      html  css  js  c++  java
  • iOS学习之二维码扫描

      这几天刚好将本人高仿新浪微博的事情进行一个阶段性的tag,在此也将这个项目在实现二维码扫描这个功能来做一个简要的记录。关于高仿新浪微博的源代码,本人已经将全部代码托管到github,地址在这里。欢迎大家指正。接下来我们来看看QRCode扫描的实现。

      关于二维码的扫描,网上说的最多的框架莫过于ZBar和ZXing框架,本人刚开始也是想使用第三方框架,但是,在iOS7之后苹果官方已经提供了二维码扫描方法,而且实现起来还是蛮简单的,故而选择原生态方法。不过,我们还是来看看,如何使用ZBar实现二维码扫描。

      首先在github上下载ZBar代码,然后将如下的相关类库添加进去: 

    AVFoundation.framwork, CoreMedia.framework, CoreVideo.framework, libiconv.dylib 和libzbar.a

      接下来在.h文件中#import "ZBarSDK.h",同时添加代理ZBarReaderDelegate,然后在.m文件中添加如下代码:

    -(void)sysbutbuttonclick{
         
         ZBarReaderViewController *reader = [ZBarReaderViewController new];
         reader.readerDelegate = self;
         ZBarImageScanner *scanner = reader.scanner;
         
         [scanner setSymbology: ZBAR_I25
                        config: ZBAR_CFG_ENABLE
                            to: 0];
         [self presentModalViewController: reader    animated: YES];
     }
     
     - (void) imagePickerController: (UIImagePickerController*) reader
      didFinishPickingMediaWithInfo: (NSDictionary*) info
     {
         
         NSLog(@"info=%@",info);
         // 得到条形码结果
         id<NSFastEnumeration> results =[info objectForKey: ZBarReaderControllerResults];
         ZBarSymbol *symbol = nil;
         for(symbol in results)
             // EXAMPLE: just grab the first barcode
             break;
         
         
         UIAlertView *alert=[[UIAlertView alloc] initWithTitle:@"信息提示!" message:symbol.data delegate:self cancelButtonTitle:@"取消" otherButtonTitles:@"确定", nil];
         [alert show];
     }
    

       最后触发扫描事件的时候调用sysbutbuttonclick即可。

      当然,本人在项目中使用的是苹果官方提供的,并将其实现单独封装,以方便使用,源代码地址在这里。欢迎大家指正。

    接下来主要讲讲如何实现,其实我们只需要三个步骤即可实现二维码扫描功能:

      1)导入AVFoundation框架,import<AVFoundation/AVFoundation.h>;

      2)设置一个用于显示扫描的view;

      3)实例化AVCaptureSession、AVCaptureVideoPreviewLayer。

    具体实现方式如下:

      1)添加开始扫描方法:

    - (void)startReading
    {
        NSError *error;
        
        //1.初始化捕捉设备(AVCaptureDevice),类型为AVMediaTypeVideo
        AVCaptureDevice *captureDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
        
        //2.用captureDevice创建输入流
        AVCaptureDeviceInput *input = [AVCaptureDeviceInput deviceInputWithDevice:captureDevice error:&error];
        if (!input) {
            NSLog(@"%@", [error localizedDescription]);
        }
        
        //3.创建媒体数据输出流
        AVCaptureMetadataOutput *captureMetadataOutput = [[AVCaptureMetadataOutput alloc] init];
        
        //4.实例化捕捉会话
        _captureSession = [[AVCaptureSession alloc] init];
        //4.1.将输入流添加到会话
        [_captureSession addInput:input];
        //4.2.将媒体输出流添加到会话中
        [_captureSession addOutput:captureMetadataOutput];
        
        //5.创建串行队列,并加媒体输出流添加到队列当中
        dispatch_queue_t dispatchQueue;
        dispatchQueue = dispatch_queue_create("myScanQueue", NULL);
        //5.1.设置代理
        [captureMetadataOutput setMetadataObjectsDelegate:self queue:dispatchQueue];
        //5.2.设置输出媒体数据类型为QRCode
        [captureMetadataOutput setMetadataObjectTypes:[NSArray arrayWithObject:AVMetadataObjectTypeQRCode]];
        
        //6.实例化预览图层
        _videoPreviewLayer = [[AVCaptureVideoPreviewLayer alloc] initWithSession:_captureSession];
        
        //7.设置预览图层填充方式
        [_videoPreviewLayer setVideoGravity:AVLayerVideoGravityResizeAspectFill];
        
        //8.设置图层的frame
        [_videoPreviewLayer setFrame:_viewPreview.layer.bounds];
        
        //9.将图层添加到预览view的图层上
        [_viewPreview.layer addSublayer:_videoPreviewLayer];
        
        //10.设置扫描范围
        captureMetadataOutput.rectOfInterest = CGRectMake(0.2f, 0.2f, 0.8f, 0.8f);
        //10.1.扫描框
        _boxView = [[UIView alloc] initWithFrame:CGRectMake(_viewPreview.bounds.size.width * 0.1f, _viewPreview.bounds.size.height * 0.2f, _viewPreview.bounds.size.width * 0.8f, _viewPreview.bounds.size.width * 0.8f)];
        _boxView.layer.borderColor = kRangeColor;
        _boxView.layer.borderWidth = 1.0f;
        [_viewPreview addSubview:_boxView];
        //10.2.扫描线
        _scanLayer = [[CALayer alloc] init];
        _scanLayer.frame = CGRectMake(0, 0, _boxView.bounds.size.width, kLineBorad);
        _scanLayer.backgroundColor = kLineColor;
        [_boxView.layer addSublayer:_scanLayer];
        
        NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:0.2f target:self selector:@selector(moveScanLayer:) userInfo:nil repeats:YES];    
        [timer fire];
        
        //11.开始扫描
        [_captureSession startRunning];
    }
    

       2)实现代理方法:

    #pragma mark - AVCaptureMetadataOutputObjectsDelegate
    - (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputMetadataObjects:(NSArray *)metadataObjects fromConnection:(AVCaptureConnection *)connection
    {
        NSString *urlStr;
        //判断是否有数据
        if (metadataObjects != nil && [metadataObjects count] > 0) {
            AVMetadataMachineReadableCodeObject *metadataObj = [metadataObjects objectAtIndex:0];
            //判断回传的数据类型
            if ([[metadataObj type] isEqualToString:AVMetadataObjectTypeQRCode]) {
                urlStr = metadataObj.stringValue;
                [self performSelectorOnMainThread:@selector(stopReading) withObject:nil waitUntilDone:NO];
            }
        }
    
        _videoPreviewLayer.hidden = YES;
        _webView.hidden = NO;
        NSURLRequest *request =[NSURLRequest requestWithURL:[NSURL URLWithString:urlStr]];
        [self.webView loadRequest:request];    
    }
    

       3)设置好页面布局,用来展现扫描结果即可。

    以上就是二维码扫描实现简要过程,希望对大家有所帮助。

  • 相关阅读:
    Java实现 LeetCode 802 找到最终的安全状态 (DFS)
    Java实现 LeetCode 802 找到最终的安全状态 (DFS)
    Java实现 LeetCode 802 找到最终的安全状态 (DFS)
    Java实现 LeetCode 804 唯一摩尔斯密码词 (暴力)
    Java实现 LeetCode 803 打砖块 (DFS)
    Java实现 LeetCode 804 唯一摩尔斯密码词 (暴力)
    Java实现 LeetCode 803 打砖块 (DFS)
    Java实现 LeetCode 804 唯一摩尔斯密码词 (暴力)
    英文标点
    post sharp 与log4net 结合使用,含执行源码 转拷
  • 原文地址:https://www.cnblogs.com/chars/p/5077887.html
Copyright © 2011-2022 走看看