IOS AVFoundation QRCode Scan

来源:互联网 发布:求几本好看网络黄书 编辑:程序博客网 时间:2024/05/15 23:46

使用 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 0