【Objective-C】QR 코드를 읽는 것만의 기능을 구현

18072 단어 XcodeObjective-C

했던 일



AVFoundation.framework를 사용하여 QR 코드 읽기

개발 환경


  • X-code10.1
  • 언어: objective-c

  • 조속하지만 보충



    코드에는 자신이 없습니다.
    일단 움직였다! 레벨을 기재하고 있으므로, 주의해 주세요(´・ω・`)
    ※물론 동작 확인은 하고 있습니다.
    지적 등 있으면, 코멘트 란에 주시면 다행입니다.

    구현 내용



    HomeViewController 버튼을 누르고 → QrCodeReaderViewController를 시작하고
    QR 코드의 URL을 로그 출력

    구현 내용



    + 버튼에서 AVFoundation.framework 추가


    HomeViewController에 storyBord에 버튼을 설치합니다.
    버튼을 누르면 QrCodeReaderViewController로 전환합니다.

    HomeViewController.m
    - (IBAction)pushQRCodeReaderButton:(UIButton *)sender {
        // QRコード読み取り画面を起動
        UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"Main" bundle:nil];
        QrCodeReaderViewController *qrCodeReaderViewController = [storyboard instantiateViewControllerWithIdentifier:@"QrCodeReaderViewController"];
        UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:qrCodeReaderViewController];
        [self presentViewController:navigationController animated:YES completion:nil];
    }
    

    QrCodeReaderViewController.m
    #import "QrCodeReaderViewController.h"
    #import <AVFoundation/AVFoundation.h>
    
    @interface QrCodeReaderViewController () <AVCaptureMetadataOutputObjectsDelegate>
    
    /// カメラのセッション
    @property (strong, nonatomic) AVCaptureSession* session;
    
    @end
    
    @implementation QrCodeReaderViewController
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        // 閉じるボタン
        UIBarButtonItem * closeButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemStop target:self action:@selector(cancel:)];
        self.navigationItem.rightBarButtonItem = closeButtonItem;
        // カメラを起動する
        [self startCameraSession];
    }
    /// カメラを起動する
    -(void)startCameraSession {
        // カメラを取得→AVMediaTypeVideoを使用
        AVCaptureDevice *device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
        // セッション作成
        self.session = [[AVCaptureSession alloc] init];
        // 入力
        AVCaptureDeviceInput *input = [AVCaptureDeviceInput deviceInputWithDevice:device error:nil];
    
        if (input) {
            // セッションにAVCaptureDeviceInputオブジェクトを追加
            [self.session addInput:input];
            // 出力
            AVCaptureMetadataOutput *output = [[AVCaptureMetadataOutput alloc] init];
            // セッションにAVCaptureMetadataOutputオブジェクトを追加
            [self.session addOutput:output];
            // 読み取りたいバーコードの種類を指定
            [output setMetadataObjectsDelegate:self queue:dispatch_get_main_queue()];
            [output setMetadataObjectTypes:@[AVMetadataObjectTypeQRCode, AVMetadataObjectTypeEAN13Code]];
            // プレビュー用のAVCaptureVideoPreviewLayerを生成してViewControllerにサブレイヤとして追加する
            AVCaptureVideoPreviewLayer *preview = [AVCaptureVideoPreviewLayer layerWithSession:self.session];
            // カメラを縦いっぱいに表示
            preview.videoGravity = AVLayerVideoGravityResizeAspectFill;
            preview.frame = CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height);
            [self.view.layer insertSublayer:preview atIndex:0];
    
            // セッションの動作を開始する→実際にデータが取得できるようになる
            [self.session startRunning];
        } else {
            // カメラの使用が未許可の(初回に表示されるアラートで「許可しない」を選択した)時
            UIAlertController *alertCntrl = [UIAlertController alertControllerWithTitle:@"確認"
                                                                                message:[@"端末の設定画面からカメラの使用を許可してください。" stringByReplacingOccurrencesOfString:@"\\n" withString:@"\n"]
                                                                         preferredStyle:UIAlertControllerStyleAlert];
            // ボタン追加
            [alertCntrl addAction:[UIAlertAction actionWithTitle:@"OK"
                                                           style:UIAlertActionStyleCancel handler:^(UIAlertAction *action) {
                                                               [self dismissViewControllerAnimated:YES completion:nil];
                                                           }]];
            [self presentViewController:alertCntrl animated:YES completion:nil];
        }
    }
    
    /// 閉じるボタン
    - (void)cancel:(UIBarButtonItem *)barButtonItem {
        [self dismissViewControllerAnimated:YES completion:nil];
    }
    
    /// QRコード読み取り時に呼ばれる
    - (void)captureOutput:(AVCaptureOutput *)captureOutput
    didOutputMetadataObjects:(NSArray *)metadataObjects
           fromConnection:(AVCaptureConnection *)connection {
        for (AVMetadataObject *data in metadataObjects) {
            if (![data isKindOfClass:[AVMetadataMachineReadableCodeObject class]]) continue;
            // QRコードデータの時
            NSString *qrCodeDataStr = [(AVMetadataMachineReadableCodeObject *)data stringValue];
            if ([data.type isEqualToString:AVMetadataObjectTypeQRCode]) {
                NSURL *url = [NSURL URLWithString:qrCodeDataStr];
                if ([[UIApplication sharedApplication] canOpenURL:url]) {
                    NSLog(@"%@",url);
                }
            }
        }
        // 画面を閉じる
        [self dismissViewControllerAnimated:YES completion:nil];
    }
    
    @end
    

    마지막으로 info.plist 편집


    info.plist에 Privacy - Camera Usage Description를 추가하는 것을 잊으면
    아래의 오류로 앱이 충돌하므로 주의합시다.

    [access] This app has crashed because it attempted to access privacy-sensitive data without a usage description. The app's Info.plist must contain an NSCameraUsageDescription key with a string value explaining to the user how the app uses this data.

    참고


  • AVFoundation의 캡처 기능 정보
  • AVFoundation에서 카메라를 표시하는 매우 짧은 샘플
  • iOS11에서는 이미지를 앨범 저장하는 앱은 Privacy에 추가해야 함
  • iOS/AVFoundation/Capture
  • 좋은 웹페이지 즐겨찾기