Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Delegate method being invoked multiple times, even after returning to a view

I'm creating an app that uses the new barcode scanner in iOS 7 but I'm having a some problems with the delegate method. The scanner correctly identifies the barcodes and invokes the delegate method, but it does it too fast so the invocation happens many times in a row resulting in a segue being performed multiple times. Delegate method below.

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

The issue is that if I do not set connection.enabled = NO in the opening line, the delegate is invoked multiple times causing a corrupt view hierarchy (and then a crash). The other issue is that when I do disable connection and then re-enable the connection using self.conn = YES in viewWillAppear, the delegate will be invoked repeatedly from prior scans when returning to the view. This then causes another corruption in the view hierarchy.

So to sum it up: Either the delegate method is being invoked multiple times in quick succession or the delegate is being invoked with (old) scans when returning to the view. Any help would be appreciated.

Edit: I've partially managed to get around the problem with some fidgeting with the delegate, but I still have a problem with the delegate method being invoked multiple times. If you go back from the next viewcontroller in less than five seconds, the delegate method will be invoked again.

like image 935
hav Avatar asked Sep 30 '13 11:09

hav


1 Answers

I think you have started captureSession using captureSession?.startRunning() method but didn't stop it once you got output from QRCode in delegate...

Just Use this [captureSession stopRunning]; // In Objective-C

below is what I have done for same issue in swift

// MARK: - AVCapture delegate to find metadata if detected

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)
        }
    }
}
like image 131
SAGAR RODE Avatar answered Nov 08 '22 02:11

SAGAR RODE