iOS 开发AVFoundation系统原生二维码扫描实现

/* 先在项目中导入AVFoundation.framework框架 */
#import <UIKit/UIKit.h>
#import <AVFoundation/AVFoundation.h>
@interface QRViewController : UIViewController
{
    /** * AVCaptureSession:AVFoundation中的核心类,用于通过硬件获取、处理和输出视频。一个Capture Session由多个输入和多个输出组成,并控制输出帧的格式和分辨率。 AVCaptureVideoPreviewLayer:用于显示摄像头捕捉到得视频到UI。 */
    AVCaptureSession *_captureSession;
    AVCaptureVideoPreviewLayer *_previewLayer;
}

#import "QRViewController.h"
#define Width self.view.frame.size.width
#define Height self.view.frame.size.height
@interface QRViewController ()<AVCaptureMetadataOutputObjectsDelegate>
{
    int num;
    BOOL upOrdown;
    NSTimer *timer;
    //自定义界面
    UIImageView *imageView;
    UIButton *scanButton;
    UILabel *labIntroudction;
    UIImageView *line;
}
@end

@implementation QRViewController

- (void)viewDidLoad {

    [super viewDidLoad];
    _previewLayer.frame = self.view.frame;


    [self initWith];
    [self setupCaptureSession];
    [self.view addSubview:scanButton];
    [self.view addSubview:labIntroudction];
    [self.view addSubview:imageView];

    upOrdown = NO;
    num =0;
    timer = [NSTimer scheduledTimerWithTimeInterval:.02 target:self selector:@selector(animation) userInfo:nil repeats:YES];

}

//自定义界面
 - (void)initWith
{
    scanButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
    [scanButton setTitle:@"取消" forState:UIControlStateNormal];
    scanButton.frame = CGRectMake(50, Height - 200, Width - 100, 50);
    scanButton.backgroundColor = [[UIColor blackColor]colorWithAlphaComponent:0.5];
    [scanButton addTarget:self action:@selector(backAction) forControlEvents:UIControlEventTouchUpInside];
    labIntroudction= [[UILabel alloc] initWithFrame:CGRectMake(50, 100, Width - 100, 50)];
    labIntroudction.numberOfLines = 0;
    labIntroudction.textColor=[UIColor whiteColor];
    labIntroudction.text=@"将二维码图像置于矩形方框内,离手机摄像头10CM左右,系统会自动识别。";
    labIntroudction.font = [UIFont systemFontOfSize:16.0];
    labIntroudction.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:0.5];


    imageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"pick_bg.png"]];
    imageView.frame = CGRectMake(40, 170, Width - 80, Width - 80);
    _line = [[UIImageView alloc] initWithFrame:CGRectMake(10, 10, imageView.frame.size.width - 20, 2)];
    _line.image = [UIImage imageNamed:@"line.png"];
    [imageView addSubview:_line];
    self.view.backgroundColor = [UIColor clearColor];

}

-(void)animation
{
    if (upOrdown == NO) {
        num ++;
        _line.frame = CGRectMake(10, 10 + 2*num, imageView.frame.size.width - 20, 2);
        if (2*num == CGRectGetHeight(imageView.frame) - 20) {
            upOrdown = YES;
        }
    }
    else {
        num --;
        _line.frame = CGRectMake(10, 10 + 2*num, imageView.frame.size.width - 20, 2);
        if (num == 0) {
            upOrdown = NO;
        }
    }

}
-(void)backAction
{

    [self dismissViewControllerAnimated:YES completion:^{
        [timer invalidate];
    }];
}

/** * 这个方法用于建立capture session。 如果session已经存在,则直接返回。 初始化video device,若设备没有摄像头,则直接返回。 初始化capture session。 通过video device创建video input。 查询session是否接受一个输入,如果接受,添加输入到session中。 最后,创建预览层并为其指定要预览的capture session。 */
- (void)setupCaptureSession {
    if (_captureSession) return;
    /* AVCaptureDevice:封装设备上的物理摄像头。对iPhone而言有前后两个摄像头。 AVCaptureDeviceInput:要添加一个AVCaptureDevice到session中,需要用AVCaptureDeviceInput来包裹一下。 */
   // 首先我们应该判断当前设备是否有捕获数据流的设备。
     AVCaptureDevice *videoDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];

    if (!videoDevice) {
        NSLog(@"No video camera on this device!");
        return;
    }
     AVCaptureDeviceInput *input = [AVCaptureDeviceInput deviceInputWithDevice:videoDevice error:nil];
    //初始化一个 CaptureSession对象
    _captureSession = [[AVCaptureSession alloc] init];
    //设置会话的输入设备
    if ([_captureSession canAddInput:input])
    {
        [_captureSession addInput:input];
    }

    //对应输出
    AVCaptureMetadataOutput *captureMetadataOutput = [[ AVCaptureMetadataOutput alloc] init];

    [_captureSession addOutput:captureMetadataOutput];

    //设置扫描区域
    [captureMetadataOutput setRectOfInterest:CGRectMake(imageView.frame.origin.y/ Height ,imageView.frame.origin.x/ Width , imageView.frame.size.width / Height, imageView.frame.size.height / Width)];
    //创建一个队列
    dispatch_queue_t metadataQueue = dispatch_queue_create("myQueue", 0);
    [captureMetadataOutput setMetadataObjectsDelegate:self queue:metadataQueue];
    [captureMetadataOutput setMetadataObjectTypes:[NSArray arrayWithObject:AVMetadataObjectTypeQRCode]];
    if([_captureSession canAddOutput:captureMetadataOutput])
    {
        [_captureSession addOutput:captureMetadataOutput];
    }

    // 降捕获的数据流展现出来
    _previewLayer = [[AVCaptureVideoPreviewLayer alloc] initWithSession:_captureSession];
    _previewLayer.videoGravity = AVLayerVideoGravityResizeAspectFill;
    [_previewLayer setFrame:self.view.layer.bounds];

    [self.view.layer addSublayer:_previewLayer];

  // 开始捕获
    [ _captureSession startRunning];

}

- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputMetadataObjects:(NSArray *)metadataObjects fromConnection:(AVCaptureConnection *)connection
{
  // 判断是否有数据,是否是二维码数据
    if (metadataObjects != nil && [metadataObjects count] > 0) {
        AVMetadataMachineReadableCodeObject *metadataObj = [metadataObjects objectAtIndex:0];
            //获得扫描的数据,并结束扫描
            [self dismissViewControllerAnimated:YES completion:^{
                [timer invalidate];
                if(metadataObj.stringValue && [metadataObj.stringValue rangeOfString:@"http:"].location != NSNotFound)
                {
                    NSString *regex = @"http+:[^\\s]*";
                    NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF MATCHES %@",regex];
                    // 正则表达式判断 是否包含 http:
                    if ([predicate evaluateWithObject:metadataObj.stringValue])
                    {
                        // 判断是不是我们自己的二维码
                        if ([metadataObj.stringValue rangeOfString:@"http://m.pinlehuo.com/api.php"].location != NSNotFound) {
                            NSLog(@"-------%@", metadataObj.stringValue);
                        }else{
                            [[UIApplication sharedApplication]openURL:[NSURL URLWithString:metadataObj.stringValue]];
                        }
                    }
                } else {
                    NSLog(@"symbol.data = %@", metadataObj.stringValue);
            }
        }];   
    }
}

@end

你可能感兴趣的:(Foundation,iOS二维码扫描)