AVCaptureSession - Stop Running - долго-долго

Я использую ZXing для приложения, это в основном тот же код, что и исходный код ZXing, за исключением того, что я позволяю сканировать несколько раз подряд (т.е. ZXingWidgetController не обязательно отклоняется, как только что-то обнаруживается).

Я испытываю длительное замораживание (иногда оно никогда не заканчивается), когда я нажимаю кнопку отклонения этого вызова.

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

    [self stopCapture];

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


} 

с участием

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

(обратите внимание, что rejectModalViewController, удаляющий представление, находится в методе делегата)

У меня зависание происходит только при отклонении, только если я сделал несколько сканирований подряд, и только с iPhone 4 (с 4S зависаний нет)

Есть идеи ?

Ваше здоровье

ПЗУ


person Romain Dorange    schedule 10.08.2012    source источник
comment
Трудно предложить что-то конструктивное. UIKit очень запутывается и делает подобные вещи, если вы делаете вызовы из основного потока, но ничто в вашем описании не покажет доказательств этого. В противном случае нет ничего известного, что вызывает зависание так, как вы описываете, и ничего очевидного в том, что вы написали. Так что, скорее всего, что-то не показано, и единственный способ узнать это - отладить это...   -  person smparkes    schedule 13.08.2012
comment
Я вижу, что это не проблема с iOS 9   -  person onmyway133    schedule 04.05.2016


Ответы (1)


Согласно примеру контроллера AV Cam View, вызов startRunning или stopRunning не возвращает результат пока сеанс не завершит запрошенную операцию. Поскольку вы отправляете эти сообщения в сеанс в основном потоке, он замораживает весь пользовательский интерфейс до завершения запрошенной операции. Я бы порекомендовал вам обернуть свои вызовы в асинхронную отправку, чтобы представление не блокировалось.

- (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];
   }
} 
person Endama    schedule 22.10.2012
comment
Будьте осторожны с этим! stopCapture управляет иерархией представлений в соответствии с приведенным выше кодом. Никогда не манипулируйте GUI из-за пределов потока GUI. - person Krumelur; 23.10.2012
comment
Ааа, хороший улов @Krumelur, да, вызов [self.prevLayer removeFromSuperlayer] должен выполняться в основном потоке - person Endama; 23.10.2012
comment
Спасибо за Ваш ответ. Я знаю, что немного опоздал, но помощь была действительно полезной! - person Romain Dorange; 23.03.2013
comment
@Endama Я пытаюсь реализовать это решение. Я не очень понимаю ваш комментарий о том, что [self.prevLayer removeFromSuperlayer] делается в основной ветке. - person NSologistic; 21.05.2015
comment
@NSologistic Вы не можете манипулировать никакими представлениями, если они не выполняются в основном потоке. Метод stopCapture вызывает метод removeFromSuperlayer. Удаление и добавление любых элементов представления всегда необходимо выполнять в основном потоке. - person Endama; 22.05.2015