IOS AVFoundation QRCode Scan

271 篇文章 0 订阅
61 篇文章 0 订阅
使用 AVFoundation 實現 QRCode 掃描

note : only available after ios7

AVCaptureMetadataOutput 在 ios7 擴充了能夠辨識一維條碼和二維條碼的功能

而目前 zxing 似乎也還不支援 arm64 的架構

因此若 app 只打算支援 ios7 以上的話

可以考慮使用此方式實作 QRCode 掃描功能

Code 很單純從頭到尾僅使用一個 UIViewController

另外使用 ARC 機制的請記得將 release 的部份註解或拿掉 >.0

MainViewController.h
#import <UIKit/UIKit.h>
#import <AVFoundation/AVFoundation.h>
@interface MainViewController : UIViewController<AVCaptureMetadataOutputObjectsDelegate>
    -(IBAction)buttonScan:(id)sender;      
    -(BOOL)startScan;
    -(void)stopScan;
@end
MainViewController.m
@implementation MainViewController{
    UIView *view_fore;      //前景用來放置工具列
    UIView *view_back;       //後景用來顯示Camera的畫面
    UILabel *label_value;            //顯示 QRCode 的資料
    UIBarButtonItem *baritem_start;      //掃描跟停止的 Button
    bool bool_reading;          //判斷是否正在掃描的 boolean
    AVCaptureSession *captureSession;            //Captrue連結
    AVCaptureVideoPreviewLayer *videoPreviewLayer;       //Capture output layer
    CAShapeLayer *layer_rect;            //單純畫個白框
}

- (void)viewDidLoad
{
    [super viewDidLoad];
        
    //初始化 layout 

    bool_reading = NO;     
    
    [self.view setBackgroundColor:[UIColor whiteColor]];
    
    view_back = [[UIView alloc]initWithFrame:self.view.bounds];
    [view_back setBackgroundColor:[UIColor clearColor]];
    [self.view addSubview:view_back];
    [view_back release];

    view_fore = [[UIView alloc]initWithFrame:self.view.bounds];
    [view_fore setBackgroundColor:[UIColor clearColor]];
    [self.view addSubview:view_fore];
    [view_fore release];
    
    label_value = [[UILabel alloc]initWithFrame:CGRectMake(0, 0, 320, 320)];
    [label_value setBackgroundColor:[UIColor whiteColor]];
    [label_value setTextColor:[UIColor blackColor]];
    [label_value setLineBreakMode:NSLineBreakByWordWrapping];
    [label_value setNumberOfLines:0];
    [view_back addSubview:label_value];
    [label_value release];
    
    UIToolbar *toolbar_scan = [[UIToolbar alloc]initWithFrame:CGRectMake(0, 524, 320, 44)];
    [view_fore addSubview:toolbar_scan];
    [toolbar_scan release];
    
    baritem_start = [[UIBarButtonItem alloc]initWithTitle:@"start" style:UIBarButtonItemStyleBordered target:self action:@selector(buttonScan:)];
    
    UIBarButtonItem *baritem_space = [[UIBarButtonItem alloc]initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil];
    [toolbar_scan setItems:@[baritem_space,baritem_start,baritem_space]];
    
    [baritem_space release];
    [baritem_start release];
}

-(IBAction)buttonScan:(id)sender{
    //baritem_start Button 事件
    if (!bool_reading) {
        if ([self startScan]) {
            [baritem_start setTitle:@"Stop"];
        }
    }
    else{
        [self stopScan];
        [baritem_start setTitle:@"Start"];
    }
    bool_reading = !bool_reading;
}

- (BOOL)startScan {
    //開始掃描
    NSError *error;
    AVCaptureDevice *captureDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];      //定義多媒體擷取種類為 Video
    AVCaptureDeviceInput *input = [AVCaptureDeviceInput deviceInputWithDevice:captureDevice error:&error];
    if (!input) {
        NSLog(@"%@", [error localizedDescription]);
        return NO;
    }
    
    captureSession = [[AVCaptureSession alloc] init];
    [captureSession addInput:input];
    
    AVCaptureMetadataOutput *captureMetadataOutput = [[AVCaptureMetadataOutput alloc] init];
    [captureSession addOutput:captureMetadataOutput];
    [captureMetadataOutput release];
    
    dispatch_queue_t dispatchQueue;
    dispatchQueue = dispatch_queue_create("scanQueue", 0);
   
    [captureMetadataOutput setMetadataObjectsDelegate:self queue:dispatchQueue];
    [captureMetadataOutput setMetadataObjectTypes:[NSArray arrayWithObjects:AVMetadataObjectTypeQRCode,nil]];//定義辨識種類為 AVMetadataObjectTypeQRCode 若也要同時掃描其他種類條碼可在後面加入
    
    videoPreviewLayer = [[AVCaptureVideoPreviewLayer alloc] initWithSession:captureSession];
    [videoPreviewLayer setVideoGravity:AVLayerVideoGravityResizeAspectFill];
    [videoPreviewLayer setFrame:self.view.layer.bounds];
    
    layer_rect = [CAShapeLayer layer];
    [layer_rect setFrame:self.view.bounds];
    [layer_rect setFillColor:[[UIColor clearColor] CGColor]];
    [layer_rect setStrokeColor:[[UIColor whiteColor] CGColor]];
    [layer_rect setLineWidth:3.0f];
    
    UIBezierPath *path = [UIBezierPath bezierPathWithRect:CGRectMake(20, 40, 280, 280)];
    [layer_rect setPath:[path CGPath]];
    
    [view_back.layer addSublayer:videoPreviewLayer];
    [videoPreviewLayer release];
    [view_back.layer addSublayer:layer_rect];
    
    [captureSession startRunning];
    
    dispatch_release(dispatchQueue);
    
    return YES;
}

-(void)stopScan{
    [captureSession stopRunning];
    captureSession = nil;
    
    [layer_rect removeFromSuperlayer];
    [videoPreviewLayer removeFromSuperlayer];
}

#pragma mark - AVCaptureMetadataOutputObjectsDelegate
-(void)captureOutput:(AVCaptureOutput *)captureOutput didOutputMetadataObjects:(NSArray *)metadataObjects fromConnection:(AVCaptureConnection *)connection{
    if (metadataObjects != nil && [metadataObjects count] > 0) {        //確認是否有掃到資料
        
        AVMetadataMachineReadableCodeObject *metadataObj = [metadataObjects objectAtIndex:0];
        if ([[metadataObj type] isEqualToString:AVMetadataObjectTypeQRCode]) {      //確認掃描種類

            dispatch_async(dispatch_get_main_queue(), ^(void){
                [label_value setText:[metadataObj stringValue]];
                [self stopScan];
                [baritem_start setTitle:@"Start"];
            });
            
            bool_reading = NO;
        }
    }
}

畫面如下

F196CKfRSg6DKU7nZGxu_IMG_05.png

T0GFEAXYSQCmL2cztarI_IMG_0576.png

以上~

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值