iOS7で追加されたバーコード読み込みを試す

iOSでバーコードを読み取ろうと思うと、ZXingというサードパーティ製のライブラリを利用する必要があった。
iOS7ではバーコード読み取り用のライブラリがデフォルトで入っており、簡単に利用することができる。

バーコード以外にもQRコードなどの利用頻度高そうなものも(イマサラ)追加されている。

コードの種類 定数
UPC-E AVMetadataObjectTypeUPCECode
Code 39 AVMetadataObjectTypeCode39Code
Code 39 mod 43 AVMetadataObjectTypeCode39Mod43Code
EAN-13(JANコード標準タイプ) AVMetadataObjectTypeEAN13Code
EAN-8(JANコード短縮タイプ) AVMetadataObjectTypeEAN8Code
Code 93 AVMetadataObjectTypeCode93Code
Code 128 AVMetadataObjectTypeCode128Code
PDF417 AVMetadataObjectTypePDF417Code
QRコード AVMetadataObjectTypeQRCode
Aztec code AVMetadataObjectTypeAztecCode
(参考)人の顔 AVMetadataObjectTypeFace

中でも人の顔なんかは複数人いてもちゃんと読み取れるらしい・・・

今回はxibでバーコード読み取り時のカメラを表示させるビューを用意しておいて、 そこにカメラの映像を貼り付けるやり方を書いています。

#import <AVFoundation/AVFoundation.h>
#import <AudioToolbox/AudioServices.h>
@interface BarcodeViewController : UIViewController<AVCaptureMetadataOutputObjectsDelegate>{
    AVCaptureSession *_session;
    AVCaptureDevice *_device;
    AVCaptureDeviceInput *_input;
    AVCaptureMetadataOutput *_output;
    AVCaptureVideoPreviewLayer *_prevLayer;
    UIView *_highlightView;
    IBOutlet UIView *barcodeView;
    NSString *getBarcodeString;
}
@property (weak, nonatomic) IBOutlet UIView *barcodeView;

viewdidloadは簡単に・・・

getBarcodeString = nil;
[self barcodeCap];

メインの部分の実装

-(void)barcodeCap{
    _highlightView = [[UIView alloc] init];
    _highlightView.autoresizingMask = UIViewAutoresizingFlexibleTopMargin|UIViewAutoresizingFlexibleLeftMargin|UIViewAutoresizingFlexibleRightMargin|UIViewAutoresizingFlexibleBottomMargin;
    _highlightView.layer.borderColor = [UIColor redColor].CGColor;
    _highlightView.layer.borderWidth = 3;
    [self.barcodeView addSubview:_highlightView];
    _session = [[AVCaptureSession alloc] init];
    _device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
    NSError *error = nil;
    
    _input = [AVCaptureDeviceInput deviceInputWithDevice:_device error:&error];
    if (_input) {
        [_session addInput:_input];
    } else {
        NSLog(@"Error: %@", error);
    }
    
    _output = [[AVCaptureMetadataOutput alloc] init];
    [_output setMetadataObjectsDelegate:self queue:dispatch_get_main_queue()];
    [_session addOutput:_output];
    
    _output.metadataObjectTypes = [_output availableMetadataObjectTypes];
    
    _prevLayer = [AVCaptureVideoPreviewLayer layerWithSession:_session];
    _prevLayer.frame = self.barcodeView.bounds;
    _prevLayer.videoGravity = AVLayerVideoGravityResizeAspectFill;
    [self.barcodeView.layer addSublayer:_prevLayer];
    AVCaptureConnection *con = _prevLayer.connection;
    con.videoOrientation = AVCaptureVideoOrientationLandscapeLeft;
    
    [_session startRunning];
    [self.barcodeView bringSubviewToFront:_highlightView];
}

- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputMetadataObjects:(NSArray *)metadataObjects fromConnection:(AVCaptureConnection *)connection{
    CGRect highlightViewRect = CGRectZero;
    AVMetadataMachineReadableCodeObject *barCodeObject;
    NSString *detectionString = nil;
    NSArray *barCodeTypes = @[AVMetadataObjectTypeEAN13Code, AVMetadataObjectTypeEAN8Code];
    
    for (AVMetadataObject *metadata in metadataObjects) {
        for (NSString *type in barCodeTypes) {
            if ([metadata.type isEqualToString:type]){
                barCodeObject = (AVMetadataMachineReadableCodeObject *)[_prevLayer transformedMetadataObjectForMetadataObject:(AVMetadataMachineReadableCodeObject *)metadata];
                highlightViewRect = barCodeObject.bounds;
                detectionString = [(AVMetadataMachineReadableCodeObject *)metadata stringValue];
                break;
            }
        }
        
        if (detectionString != nil){
            NSLog(@"読み込んだのは%@",detectionString);
            AudioServicesPlaySystemSound(1000);
            getBarcodeString = detectionString;
            break;
        }
    }
    _highlightView.frame = highlightViewRect;
}

AVCaptureConnection *con = _prevLayer.connection;
con.videoOrientation = AVCaptureVideoOrientationLandscapeLeft; は無くてもOK。
横画面表示させるときに必要ってだけ。
おそらくカメラアプリを作るときと似てるんじゃないかと思います。

NSArray *barCodeTypes = @[AVMetadataObjectTypeEAN13Code, AVMetadataObjectTypeEAN8Code];
この配列に認識させたいタイプを記載しておくだけです。
今回はバーコードなので、2つ入れていますが、QRコードだけの場合はAVMetadataObjectTypeQRCodeを入れることになります。

以上!