3

I use ZXing for an app, this is mainly the same code than the ZXing original code except that I allow to scan several time in a row (ie., the ZXingWidgetController is not necesseraly dismissed as soon as something is detected).

I experience a long long freeze (sometimes it never ends) when I press the dismiss button that call

- (void)cancelled {
  //  if (!self.isStatusBarHidden) {
  //      [[UIApplication sharedApplication] setStatusBarHidden:NO];
  //  }

    [self stopCapture];

    wasCancelled = YES;
    if (delegate != nil) {
        [delegate zxingControllerDidCancel:self];
    }


} 

with

- (void)stopCapture {
    decoding = NO;
#if HAS_AVFF


    if([captureSession isRunning])[captureSession stopRunning];
    AVCaptureInput* input = [captureSession.inputs objectAtIndex:0];
    [captureSession removeInput:input];
    AVCaptureVideoDataOutput* output = (AVCaptureVideoDataOutput*)[captureSession.outputs objectAtIndex:0];
    [captureSession removeOutput:output];
    [self.prevLayer removeFromSuperlayer];

    /*
     // heebee jeebees here ... is iOS still writing into the layer?
     if (self.prevLayer) {
     layer.session = nil;
     AVCaptureVideoPreviewLayer* layer = prevLayer;
     [self.prevLayer retain];
     dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 12000000000), dispatch_get_main_queue(), ^{
     [layer release];
     });
     }
     */

    self.prevLayer = nil;
    self.captureSession = nil;
#endif
}

(please notice that the dismissModalViewController that remove the view is within the delegate method)

I experience the freeze only while dismissing only if I made several scans in a row, and only with an iPhone 4 (no freeze with a 4S)

Any idea ?

Cheers

Rom

Romain Dorange
  • 831
  • 1
  • 10
  • 23
  • Hard to provide anything constructive. UIKit gets very confused and does things like this if you make calls off the main thread but nothing in your description would show evidence of that. Otherwise, there's nothing known that causes hangs the way you describe and nothing obvious in what you've written. So it's likely something not shown and the only way to know is to debug it ... – smparkes Aug 13 '12 at 16:48
  • I see it's not a problem as of iOS 9 – onmyway133 May 04 '16 at 07:29

1 Answers1

22

According to the AV Cam View Controller Example calling startRunning or stopRunning does not return until the session completes the requested operation. Since you are sending these messages to the session on the main thread, it freezes all the UI until the requested operation completes. What I would recommend is that you wrap your calls in an Asynchronous dispatch so that the view does not lock-up.

- (void)cancelled 
{
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        [self stopCapture];
    });

   //You might want to think about putting the following in another method
   //and calling it when the stop capture method finishes
   wasCancelled = YES;
   if (delegate != nil) {
        [delegate zxingControllerDidCancel:self];
   }
} 
Endama
  • 743
  • 8
  • 25
  • 3
    Be careful with that! `stopCapture` manipulates the view hierarchy according to the code above. Never manipulate GUI from outside of the GUI thread. – Krumelur Oct 22 '12 at 20:36
  • Ahh good catch @Krumelur yea the [self.prevLayer removeFromSuperlayer] calling should be done on the main thread – Endama Oct 22 '12 at 20:47
  • Thanks for your answer. I know I am a bit late but the help was really useful ! – Romain Dorange Mar 23 '13 at 17:06
  • @Endama I am trying to implement this solution. I don't really understand your comment on `[self.prevLayer removeFromSuperlayer]` being done in the main thread. – NSologistic May 21 '15 at 19:19
  • @NSologistic You can't manipulate any views unless they are done on the main thread. The stopCapture method calls removeFromSuperlayer. Removing and adding any view elements always needs to be done on the main thread. – Endama May 22 '15 at 20:46