7

iOS 7 で新しいバーコード スキャナーを使用するアプリを作成していますが、デリゲート メソッドに問題があります。スキャナはバーコードを正しく識別し、デリゲート メソッドを呼び出しますが、実行が速すぎるため、呼び出しが連続して何度も発生し、セグエが複数回実行されます。以下の委任方法。

- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputMetadataObjects:(NSArray *)metadataObjects fromConnection:(AVCaptureConnection *)connection {
    connection.enabled = NO;
    self.conn = connection;
    for (AVMetadataObject *metadata in metadataObjects) {
        if ([metadata.type isEqualToString:AVMetadataObjectTypeEAN8Code] || [metadata.type isEqualToString:AVMetadataObjectTypeEAN13Code]) {
            self.strValue = [(AVMetadataMachineReadableCodeObject *)metadata stringValue];
            NSLog(@"%@", [(AVMetadataMachineReadableCodeObject *)metadata corners]);
        }
    }
    [self performSegueWithIdentifier:@"newSegue" sender:self];
}

問題は、最初の行で設定しないconnection.enabled = NOと、デリゲートが複数回呼び出され、ビュー階層が破損する (そしてクラッシュする) ことです。もう1つの問題は、接続を無効にしてからviewWillAppearを使用して接続を再度有効にするself.conn = YESと、ビューに戻るときに以前のスキャンからデリゲートが繰り返し呼び出されることです。これにより、ビュー階層に別の破損が発生します。

要約すると、デリゲート メソッドが立て続けに複数回呼び出されているか、ビューに戻るときに (古い) スキャンでデリゲートが呼び出されています。どんな助けでも大歓迎です。

編集:デリゲートをいじることで問題を部分的に回避することができましたが、デリゲートメソッドが複数回呼び出されるという問題がまだあります。次のビューコントローラーから 5 秒以内に戻ると、デリゲート メソッドが再度呼び出されます。

4

5 に答える 5

7

captureSession?.startRunning() メソッドを使用して captureSession を開始したと思いますが、デリゲートで QRCode から出力を取得したら停止しませんでした...

これを使用するだけです [captureSession stopRunning]; // Objective-C の場合

以下は、同じ問題に対して迅速に行ったことです

// MARK: - 検出された場合にメタデータを検索するための AVCapture デリゲート

func captureOutput(captureOutput: AVCaptureOutput!, didOutputMetadataObjects metadataObjects: [AnyObject]!, fromConnection connection: AVCaptureConnection!) {

    // Check if the metadataObjects array is not nil and it contains at least one object.
    if metadataObjects == nil || metadataObjects.count == 0 {
        qrCodeFrameView?.frame = CGRectZero
        return
    }

    // Get the metadata object.
    let metadataObj = metadataObjects[0] as! AVMetadataMachineReadableCodeObject

    if metadataObj.type == AVMetadataObjectTypeQRCode {
        // If the found metadata is equal to the QR code metadata then update the status label's text and set the bounds
        let barCodeObject = videoPreviewLayer?.transformedMetadataObjectForMetadataObject(metadataObj as AVMetadataMachineReadableCodeObject) as! AVMetadataMachineReadableCodeObject
        qrCodeFrameView?.frame = barCodeObject.bounds;

        if metadataObj.stringValue != nil {
            captureSession?.stopRunning()    // Stop captureSession here... :)
            self.performSegueWithIdentifier("yourNextViewController", sender: self)
        }
    }
}
于 2016-05-06T07:45:13.343 に答える
0

回避策は、キャプチャ バーコード イベントの最初の識別後に false に切り替えられる Boolean プロパティをデリゲート クラスに追加することです。

このソリューションは、Calin Chituが提供するものとして実装されています。

プロパティ shouldSendReadBarcodeToDelegate を YES で 1 回初期化する必要もあります。

@property (nonatomic, assign) BOOL shouldSendReadBarcodeToDelegate;

- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputMetadataObjects:(NSArray *)metadataObjects fromConnection:(AVCaptureConnection *)connection 
  {
     if (!self.shouldSendReadBarcodeToDelegate)
     {
        //this means we have already captured at least one event, then we don't want   to call the delegate again
        return;
     }
     else
     {
        self.shouldSendReadBarcodeToDelegate = NO;
        //Your code for calling  the delegate should be here
     }

  }
于 2014-08-27T08:11:01.200 に答える
0

ブール値のプロパティは私にとってはうまくいきません。複数の読み取りを避けるために、操作キューの使用を終了しました。

- (void)captureOutput:(AVCaptureOutput *)captureOutput
didOutputMetadataObjects:(NSArray *)metadataObjects
       fromConnection:(AVCaptureConnection *)connection
{
    if ([self.queue operationCount] > 0) return;

    NSBlockOperation *operation = [NSBlockOperation blockOperationWithBlock:^{
        if ([metadataObjects count] > 0) {
           // Your code here: Don't forget that you are in background now, perform
           // all view related stuff on main thread
        }
    }];
    [self.queue addOperations:@[operation] waitUntilFinished:NO];
}

ビューコントローラーのコンストラクターでキューを初期化する:

self.queue = [NSOperationQueue new];
于 2014-09-12T17:07:33.117 に答える