2013-04-05 9 views
9

Próbuję osadzić prosty widok w mojej aplikacji na iPhone'a, aby wykonać szybkie migawki. Wszystko działa dobrze, ale mam pewne problemy z czasem uruchamiania aparatów. W przykładowym projekcie Apple AVCaptureSession -startRunning nie jest wykonywane w głównym wątku, co wydaje się konieczne. Konfiguruję sesję przechwytywania podczas inicjowania widoku, a także uruchamiam go w osobnym wątku. Teraz dodam AVCaptureVideoPreviewLayer w -didMoveToSuperview. Wszystko jest w porządku bez wielowątkowości (interfejs jest blokowany przez około sekundę), ale z GCD czasami działa UI, czasami trwa zbyt długo, aby interfejs mógł "odmrozić" lub wyświetlić podgląd.Jak uniknąć blokowania interfejsu użytkownika podczas korzystania z kamery iPhone'a za pośrednictwem AVFoundation?

W jaki sposób radzić sobie z opóźnieniem uruchomienia aparatu w niezawodny sposób, bez blokowania głównego wątku (samo opóźnienie nie jest problemem)?

Mam nadzieję, że chłopaki zrozumieć mój problem: D

Dzięki z góry!

BTW: Oto mój proof-of-concept-projektu (bez GCD) Jestem teraz ponowne dla innej aplikacji: http://github.com/dariolass/QuickShotView

Odpowiedz

10

Więc zorientowaliśmy się sam. Ten kod działa dla mnie i produkuje najmniejszą UI krzepnięcia:

- (void)willMoveToSuperview:(UIView *)newSuperview { 
    //capture session setup 
    AVCaptureDeviceInput *newVideoInput = [[AVCaptureDeviceInput alloc] initWithDevice:self.rearCamera error:nil]; 
    AVCaptureStillImageOutput *newStillImageOutput = [[AVCaptureStillImageOutput alloc] init]; 
    NSDictionary *outputSettings = [[NSDictionary alloc] initWithObjectsAndKeys: 
          AVVideoCodecJPEG, AVVideoCodecKey, 
          nil]; 
    [newStillImageOutput setOutputSettings:outputSettings]; 

    AVCaptureSession *newCaptureSession = [[AVCaptureSession alloc] init]; 

    if ([newCaptureSession canAddInput:newVideoInput]) { 
     [newCaptureSession addInput:newVideoInput]; 
    } 

    if ([newCaptureSession canAddOutput:newStillImageOutput]) { 
     [newCaptureSession addOutput:newStillImageOutput]; 
     self.stillImageOutput = newStillImageOutput; 
     self.captureSession = newCaptureSession; 
    } 
    // -startRunning will only return when the session started (-> the camera is then ready) 
    dispatch_queue_t layerQ = dispatch_queue_create("layerQ", NULL); 
    dispatch_async(layerQ, ^{ 
     [self.captureSession startRunning]; 
     AVCaptureVideoPreviewLayer *prevLayer = [[AVCaptureVideoPreviewLayer alloc]initWithSession:self.captureSession]; 
      prevLayer.frame = self.previewLayerFrame; 
      prevLayer.masksToBounds = YES; 
      prevLayer.videoGravity = AVLayerVideoGravityResizeAspectFill; 
      prevLayer.cornerRadius = PREVIEW_LAYER_EDGE_RADIUS; 
     //to make sure were not modifying the UI on a thread other than the main thread, use dispatch_async w/ dispatch_get_main_queue 
     dispatch_async(dispatch_get_main_queue(), ^{ 
      [self.layer insertSublayer:prevLayer atIndex:0]; 
     }); 
    }); 
} 
+0

Dzięki! Kluczem dla mnie było wykonanie "startu" programu AVCaptureSession "startRunning" i "stopRunning" na wątku tła. – the4kman

-1

myślę inny sposób, aby uniknąć jest to, że można umieścić swoje „start” kod aparatu w viewDidAppear, zamiast umieszczać je w viewWillAppear.

+0

Nie dotyczy to problemu kosztownej funkcji wykonywanej w głównym wątku. Wciąż możesz wykonać to wcześnie (np. W 'viewWillAppear') i nie blokować głównych wątków –