iOS开发:使用苹果自带框架实现二维码和条形码扫描

扫描二维码和条形码,用的是AVFoundation,判断如果是URL就打开web页面。


预览



思路

  • AVFoundation框架很强大,调摄像头各种硬件
  • 判断URL用正则表达式
主要代码
//
//  CaptureViewController.m
//  ScanCode
//
//  Created by yxhe on 16/6/2.
//  Copyright © 2016年 yxhe. All rights reserved.
//


#import <AVFoundation/AVFoundation.h>
#import "CaptureViewController.h"
#import "BrowserViewController.h"

const char *kScanCodeQueueName = "ScanCodeQueue"; //the new process queue indentifier


@interface CaptureViewController ()<AVCaptureMetadataOutputObjectsDelegate>
{
    AVCaptureSession *session; //the session of captrue
    BOOL isLightOpen;
}

@property (nonatomic, strong) UIView *cameraView; //the camera frame view
@property (nonatomic, strong) UIButton *openLightBtn; //open the light

@end

@implementation CaptureViewController

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view.
    
    //add the cameara view
    _cameraView = [[UIView alloc] initWithFrame:CGRectMake(0, 100, self.view.frame.size.width, self.view.frame.size.width)];
    _cameraView.backgroundColor = [UIColor lightGrayColor];
    [self.view addSubview:_cameraView];
    
    //add a button to switch light
    isLightOpen = NO;
    UIButton *lightButton = [UIButton buttonWithType:UIButtonTypeCustom];
    lightButton.frame = CGRectMake(self.view.frame.size.width/2 - 50, 500, 100, 50);
    [lightButton setTitle:@"open_light" forState:UIControlStateNormal];
    [lightButton setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
    [lightButton setTitleColor:[UIColor greenColor] forState:UIControlEventTouchDown];
    [lightButton addTarget: self action:@selector(switchLight) forControlEvents:UIControlEventTouchUpInside];
    [self.view addSubview:lightButton];
    
    
    
    //start capture
    [self initCapture];
    [session startRunning];
    
}

- (void)loadView
{
    [super loadView];
//    [self initCapture];

}

- (void)viewDidAppear:(BOOL)animated
{
    [super viewDidAppear:animated];
//    [self initCapture];
}


- (void)switchLight
{
    AVCaptureDevice *device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
    //toggle the light
    isLightOpen = !isLightOpen;
    //turn on or off the light
    if([device hasTorch])
    {
        [device lockForConfiguration:nil];
        
        if(isLightOpen)
            [device setTorchMode:AVCaptureTorchModeOn];
        else
            [device setTorchMode:AVCaptureTorchModeOff];
        
        [device unlockForConfiguration];
    }
        
}

- (void)initCapture
{
    //get the camera device
    AVCaptureDevice * device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
    
    //create the session
    session = [[AVCaptureSession alloc]init];
    
    //create input
    NSError *error;
    AVCaptureDeviceInput * input = [AVCaptureDeviceInput deviceInputWithDevice:device error:&error];
    if(!input)
    {
        NSLog(@"%@", [error localizedDescription]);
        return;
    }
    [session addInput:input];
    
    //create output
    AVCaptureMetadataOutput * output = [[AVCaptureMetadataOutput alloc]init];
    [session addOutput:output];
    
    //make it run at a new process
    dispatch_queue_t dispatchQueue;
    dispatchQueue = dispatch_queue_create(kScanCodeQueueName, NULL);
    [output setMetadataObjectsDelegate:self queue:dispatchQueue];
    
    
    //set the sampling rate
    [session setSessionPreset:AVCaptureSessionPresetHigh];
    
    //set the code type ,ex:QR and bar code
    if([output.availableMetadataObjectTypes containsObject:AVMetadataObjectTypeQRCode])
        [output setMetadataObjectTypes:[NSArray arrayWithObjects:AVMetadataObjectTypeQRCode,AVMetadataObjectTypeEAN13Code, AVMetadataObjectTypeEAN8Code, AVMetadataObjectTypeCode128Code, nil]];
    
    //add the camera layer
    AVCaptureVideoPreviewLayer *captureLayer = [AVCaptureVideoPreviewLayer layerWithSession:session];
    captureLayer.videoGravity=AVLayerVideoGravityResizeAspectFill;
    captureLayer.frame=self.cameraView.layer.bounds;
    [self.cameraView.layer insertSublayer:captureLayer atIndex:0]; //or use the addsublayer
//    [self.cameraView.layer addSublayer:captureLayer];
    
}

#pragma mark - capture delegate
-(void)captureOutput:(AVCaptureOutput *)captureOutput didOutputMetadataObjects:(NSArray *)metadataObjects fromConnection:(AVCaptureConnection *)connection
{
    if (metadataObjects && metadataObjects.count>0)
    {
        //stop the capture
        [session stopRunning];
        AVMetadataMachineReadableCodeObject * metadataObject = [metadataObjects objectAtIndex : 0 ];
        //do sth to handle the capture result
        [self performSelectorOnMainThread:@selector(handleResult:) withObject:metadataObject waitUntilDone:NO];
    }
}

- (void)handleResult:(AVMetadataMachineReadableCodeObject *)metadataObject
{

    NSLog(@"%@", metadataObject.type);
    if([metadataObject.type isEqualToString:AVMetadataObjectTypeQRCode])
        NSLog(@"QR code");
    else
        NSLog(@"other code");
    
    NSString *captureStr = metadataObject.stringValue;
    NSLog(@"%@",captureStr);
    
    //if the string is URL, then push a view and open the website, otherwise just pop a dialog to show the msg
    if([self isURL:captureStr])
    {
        BrowserViewController *browserViewController = [[BrowserViewController alloc] init];
        browserViewController.urlStr = captureStr;
        
        [self.navigationController pushViewController:browserViewController animated:YES];
    }
    else
    {
        UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"scan result"
                                                        message:captureStr
                                                       delegate:nil
                                              cancelButtonTitle:@"ok"
                                              otherButtonTitles: nil];
        [alert show];
    }
}

//use regular expression to recognize URL
- (BOOL)isURL:(NSString *)str
{
    NSString *regex = @"[a-zA-z]+://[^s]*";
    NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", regex];
    return [predicate evaluateWithObject:str];
}

- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}


@end
其中二维码识别较灵敏,条形码稍显迟钝。

源代码下载

csdn: 二维码扫码
github: ScanCode


你可能感兴趣的:(ios)