システムのAVMetadataObjectクラスを使用してQRコードスキャンを実現

6135 ワード

前言
QRコードについては、ここではあまり説明しないで、直接キビ百科に行って、QR code.IOS 7のリンクを添付する前に、開発者がスキャンコードのプログラミングを行うときは、サードパーティのライブラリを借りるのが一般的です.ZBarSDKaとZXingObjC,IOS 7以降,システムのAVMetadataObjectクラスにおいて,QRコードを解析するためのインタフェースを提供するのが一般的である.試験により,原生APIを用いたスキャンと処理の効率は非常に高く,サードパーティ製ライブラリよりはるかに高い.
スキャン
公式に提供されているインタフェースは非常に簡単で、コードを直接見て、主にAVFoundationを使用しています.
 
@interface ViewController ()//           
{
    AVCaptureSession * session;//         
}
@end
@implementation ViewController
 
- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    //      
    AVCaptureDevice * device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
    //     
    AVCaptureDeviceInput * input = [AVCaptureDeviceInput deviceInputWithDevice:device error:nil];
    if (!input) return;
    //     
    AVCaptureMetadataOutput * output = [[AVCaptureMetadataOutput alloc]init];
    //            
    [output setMetadataObjectsDelegate:self queue:dispatch_get_main_queue()];
    //        
    CGRect scanCrop=[self getScanCrop:_scanWindow.bounds readerViewBounds:self.view.frame];
     output.rectOfInterest = scanCrop;
    //       
    _session = [[AVCaptureSession alloc]init];
    //      
    [_session setSessionPreset:AVCaptureSessionPresetHigh];
    
    [_session addInput:input];
    [_session addOutput:output];
    //           (             )
    output.metadataObjectTypes=@[AVMetadataObjectTypeQRCode,AVMetadataObjectTypeEAN13Code, AVMetadataObjectTypeEAN8Code, AVMetadataObjectTypeCode128Code];
    
    AVCaptureVideoPreviewLayer * layer = [AVCaptureVideoPreviewLayer layerWithSession:_session];
    layer.videoGravity=AVLayerVideoGravityResizeAspectFill;
    layer.frame=self.view.layer.bounds;
    [self.view.layer insertSublayer:layer atIndex:0];
    //    
    [_session startRunning];
}

-(void)captureOutput:(AVCaptureOutput *)captureOutput didOutputMetadataObjects:(NSArray *)metadataObjects fromConnection:(AVCaptureConnection *)connection{
    if (metadataObjects.count>0) {
        //[session stopRunning];
        AVMetadataMachineReadableCodeObject * metadataObject = [metadataObjects objectAtIndex : 0 ];
        //       
        NSLog(@"%@",metadataObject.stringValue);
    }
}

いくつかの初期化されたコードにエージェントを実装する方法を加えると、QRコードスキャンの作業が完了します.ここで注意しなければならないのは、QRコードスキャンの場合、画面の真ん中にボックスを置いて、QRコードスキャンのサイズ区間を表示することです.ここでは、AVCaptureMetadataOutputクラスにrectOfInterestの属性があります.スキャン範囲を設定する役割を果たします.
このCGRectパラメータは通常のRect範囲とは異なり、4つの値の範囲はいずれも0-1であり、割合を表す.rectOfInterestは横スクリーンで計算されているので、縦スクリーンの場合はx軸とy軸を交換します.幅と高さの設定も同様です.
有効なスキャン領域を上に設定する方法は以下の通りです.
 
#pragma mark->            
-(CGRect)getScanCrop:(CGRect)rect readerViewBounds:(CGRect)readerViewBounds
{
    
    CGFloat x,y,width,height;
    
    x = (CGRectGetHeight(readerViewBounds)-CGRectGetHeight(rect))/2/CGRectGetHeight(readerViewBounds);
    y = (CGRectGetWidth(readerViewBounds)-CGRectGetWidth(rect))/2/CGRectGetWidth(readerViewBounds);
    width = CGRectGetHeight(rect)/CGRectGetHeight(readerViewBounds);
    height = CGRectGetWidth(rect)/CGRectGetWidth(readerViewBounds);
    
    return CGRectMake(x, y, width, height);
    
}

読み取り
読み取りは主にCoreImageで行われていますが、QRコードを読み取る機能はiOS 8以降でしかサポートされていません.アルバムにQRコードを呼び出して、それを読み取る必要があります.コードは以下の通りです.
 
#pragma mark->     
-(void)myAlbum{
    
    NSLog(@"    ");
    if([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypePhotoLibrary]){
        //1.        
        UIImagePickerController *controller = [[UIImagePickerController alloc] init];
        //2.    
        controller.delegate = self;
        //3.    :
        /**
         UIImagePickerControllerSourceTypePhotoLibrary,  
         UIImagePickerControllerSourceTypeCamera,  
         UIImagePickerControllerSourceTypeSavedPhotosAlbum,   
         */
        controller.sourceType = UIImagePickerControllerSourceTypeSavedPhotosAlbum;
        //4.          
        controller.modalTransitionStyle=UIModalTransitionStyleFlipHorizontal;
        [self presentViewController:controller animated:YES completion:NULL];
        
    }else{
        
        UIAlertView * alert = [[UIAlertView alloc]initWithTitle:@"  " message:@"         ,    ->  ->       !" delegate:nil cancelButtonTitle:@"  " otherButtonTitles:nil, nil];
        [alert show];
    }
    
}

アルバムエージェントを完了し、エージェントにQRコードの読み取り方法を追加します.
 
#pragma mark-> imagePickerController delegate
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{
    //1.       
    UIImage *image = info[UIImagePickerControllerOriginalImage];
    //2.        
    CIDetector*detector = [CIDetector detectorOfType:CIDetectorTypeQRCode context:nil options:@{ CIDetectorAccuracy : CIDetectorAccuracyHigh }];
    
    [picker dismissViewControllerAnimated:YES completion:^{
        //        
        NSArray *features = [detector featuresInImage:[CIImage imageWithCGImage:image.CGImage]];
        if (features.count >=1) {
            /**     */
            CIQRCodeFeature *feature = [features objectAtIndex:0];
            NSString *scannedResult = feature.messageString;
            UIAlertView * alertView = [[UIAlertView alloc]initWithTitle:@"    " message:scannedResult delegate:nil cancelButtonTitle:@"  " otherButtonTitles:nil, nil];
            [alertView show];
          
        }
        else{
            UIAlertView * alertView = [[UIAlertView alloc]initWithTitle:@"  " message:@"            !" delegate:nil cancelButtonTitle:@"  " otherButtonTitles:nil, nil];
            [alertView show];
            
        }
        
  
    }];
    
    
}

実機を使っていないので、ここではあまりスクリーンショットを与えず、シミュレータで持参した画像を読み出した結果、以下のようになりました.
Demoダウンロードリンク