2015-08-30 45 views
0

我通過教程this site(Appcoda教程)製作了帶有AVFoundation的QR碼閱讀應用程序。閱讀QR碼後,該應用程序顯示一個UIAlertView。但它需要近2分鐘(有時超過3分鐘)。我將在這裏粘貼整個ViewController.m文件。我希望這已經足夠了。 (UIAlertView處於captureOutput方法)Obj。 C - QR閱讀應用程序運行速度太慢

// 
// ViewController.m 
// Yuvio 
// 
// Created by İhsan Batuğhan YILMAZ on 29/08/15. 
// Copyright © 2015 Farabius. All rights reserved. 
// 

#import "ViewController.h" 
#import <AVFoundation/AVFoundation.h> 


@interface ViewController() 

@property (nonatomic) BOOL isReading; 

@property (nonatomic, strong) AVCaptureSession *captureSession; 
@property (nonatomic, strong) AVCaptureVideoPreviewLayer *videoPreviewLayer; 

-(BOOL)startReading; 
-(void) stopReading; 

@end 

@implementation ViewController 

- (void)viewDidLoad { 
    [super viewDidLoad]; 
    // Do any additional setup after loading the view, typically from a nib. 
    _isReading=NO; 
    _captureSession = nil; 
} 

- (void)didReceiveMemoryWarning { 
    [super didReceiveMemoryWarning]; 
    // Dispose of any resources that can be recreated. 
} 

-(IBAction)startStopReading:(id)sender { 
    if (!_isReading) { 
     if ([self startReading]) { 
      [_btnStart setTitle:@"Stop"]; 
     } 
    } 
    else{ 
     [self stopReading]; 
     [_btnStart setTitle:@"Start!"]; 
    } 

    _isReading = !_isReading; 
} 
- (BOOL)startReading { 
    NSError *error; 

    AVCaptureDevice *captureDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo]; 

    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]; 

    dispatch_queue_t dispatchQueue; 
    dispatchQueue = dispatch_queue_create("myQueue", NULL); 
    [captureMetadataOutput setMetadataObjectsDelegate:self queue:dispatchQueue]; 
    [captureMetadataOutput setMetadataObjectTypes:[NSArray arrayWithObject:AVMetadataObjectTypeQRCode]]; 

    _videoPreviewLayer = [[AVCaptureVideoPreviewLayer alloc] initWithSession:_captureSession]; 
    [_videoPreviewLayer setVideoGravity:AVLayerVideoGravityResizeAspectFill]; 
    [_videoPreviewLayer setFrame:_cameraView.layer.bounds]; 
    [_cameraView.layer addSublayer:_videoPreviewLayer]; 

    [_captureSession startRunning]; 

    return YES; 
} 

-(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]) { 

      UIAlertView *alert = [[UIAlertView alloc] 
            initWithTitle:@"QR Detected" 
            message:[metadataObj stringValue] 
            delegate:self 
            cancelButtonTitle:@"OK" otherButtonTitles:nil, nil]; 
      [alert show]; 

      [self performSelectorOnMainThread:@selector(stopReading) withObject:nil waitUntilDone:NO]; 
      [_btnStart performSelectorOnMainThread:@selector(setTitle:) withObject:@"Start!" waitUntilDone:NO]; 
      _isReading = NO; 
     } 
    } 
} 
-(void)stopReading{ 
    [_captureSession stopRunning]; 
    _captureSession = nil; 

    [_videoPreviewLayer removeFromSuperlayer]; 
    return; 
} 

@end 

回答

2

我認爲這個問題是在主線程之外使用UI函數。試試這個代碼:

-(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]) { 
      __weak ViewController *weakSelf = self; 
      dispatch_async(dispatch_get_main_queue(), ^{ 
       [weakSelf processQRCode:metadataObj]; 
      }); 
     } 
    } 
} 

-(void)processQRCode:(AVMetadataMachineReadableCodeObject *)codeObject{ 
    UIAlertView *alert = [[UIAlertView alloc] 
          initWithTitle:@"QR Detected" 
          message:[codeObject stringValue] 
          delegate:self 
          cancelButtonTitle:@"OK" otherButtonTitles:nil, nil]; 
    [alert show]; 

    [self stopReading]; 
    [_btnStart setTitle:@"Start!" forState:UIControlStateNormal]; 
    _isReading = NO; 
} 

我檢查了您的視圖控制器與此修復程序,它工作的很快。

+0

如果您認爲該問題已解決,您可以將答案標記爲正確答案。 –

+0

你的答案在單視圖應用程序中解決了我的問題。再次感謝。但是我如何在選項卡式應用程序中使用它。因爲_weak ViewController似乎不適用於選項卡式視圖應用程序。 – cameloper

+0

好吧,我發現它,只需刪除_weak ViewController * weakSelf = self;並調用方法時改用自己而不是weakSelf。 – cameloper