iOS 8 Migawka widoku, który nie został wyrenderowany, powoduje powstanie pustej migawki

228

W iOS 8 mam problem z przechwytywaniem zdjęć z aparatu, do tej pory używam tego kodu

UIImagePickerController *controller=[[UIImagePickerController alloc] init];
controller.videoQuality=UIImagePickerControllerQualityTypeMedium;
controller.delegate=(id)self;
controller.sourceType=UIImagePickerControllerSourceTypeCamera;
[self presentViewController:controller animated:YES completion:nil];

Ale w iOS 8 otrzymuję to:

Snapshotting a view that has not been rendered results in an empty snapshot. Ensure your view has been rendered at least once before snapshotting or snapshot after screen updates.

Próbowałem z rozwiązaniem dostarczonym przez ten post z

@property (strong,nonatomic)UIImagePickerController *controller;

_controller=[[UIImagePickerController alloc] init];
_controller.videoQuality=UIImagePickerControllerQualityTypeMedium;
_controller.delegate=(id)self;
_controller.sourceType=UIImagePickerControllerSourceTypeCamera;
_[self presentViewController:controller animated:YES completion:nil];

i to

...
controller.modalPresentationStyle=UIModalPresentationFullScreen;
or
controller.modalPresentationStyle=UIModalPresentationCurrentContext;
...

i to

double delayInSeconds = 0.1;
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, delayInSeconds * NSEC_PER_SEC);
dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
    [self presentViewController:controller animated:YES completion:nil];
});

i to

[self presentViewController:controller animated:YES completion:NULL];

i to

[self presentViewController:controller animated:YES completion:^{

}];

dowolny pomysł?

souvickcse
źródło
3
Mam ten sam problem, a ponadto ten błąd powoduje awarie mojej aplikacji od czasu do czasu. Mam nadzieję, że aktualizacja 8.0.2 naprawi ten błąd. Kiedy uruchamiam moją aplikację w iOS7, działa jak urok bez żadnych głupich ostrzeżeń. Wygląda na to, że iOS 8 ma długą drogę do stabilności.
NCFUSN
9
Wydarzenie z aktualizacją 8.0.2 problem ten nadal występuje
ArdenDev,
2
Miałem ten sam problem. Po zrobieniu zdjęcia przetwarzałem trochę wątku. Po przeniesieniu kodu do głównego wątku wszystko było w porządku. Tj. Mój kod wcześniej: dispatch_async(dispatch_get_main_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{zmieniłem nadispatch_async(dispatch_get_main_queue(), ^{
mikeyq6,
9
Ten sam problem występuje w iOS 8.1
Raptor
12
Zdarza się również w iOS 9.
Sebyddd

Odpowiedzi:

131

Jestem prawie pewien, że to tylko błąd w iOS 8.0. Jest to powtarzalne w przypadku najprostszych aplikacji POC, które nie robią nic więcej, jak tylko próbują zaprezentować się UIImagePickerControllertak, jak powyżej. Co więcej, według mojej wiedzy nie ma alternatywnego wzorca wyświetlania selektora / kamery obrazu. Możesz nawet pobrać przykładową aplikację Apple Using UIImagePickerController , uruchomić ją, a ona wygeneruje ten sam błąd po wyjęciu z pudełka.

To powiedziawszy, funkcjonalność nadal działa dla mnie. Czy oprócz ostrzeżenia / błędu masz problemy z działaniem aplikacji?

KevinH
źródło
2
Tak, prawdopodobnie jest to błąd, kod również działa dobrze dla mnie.
souvickcse
4
@souvickcse Wystąpił również ten błąd. Ilekroć to nastąpi, podgląd obrazu, który pojawia się po zrobieniu nowego zdjęcia, jest całkowicie czarny. Jednak przyciski „Re-Take” i „Use Photo” u dołu ekranu nadal pojawiają się i działają poprawnie. Czy jesteś świadkiem tego samego zachowania?
Barry Beerman
3
@souvickcse Korzystam z najnowszej linii bazowej wtyczki aparatu telefonicznego znajdującej się tutaj: github.com/apache/cordova-plugin-camera . Wszystko działa dobrze z iOS 7.1 uruchomiony na iPhone 5, ale nie mogę znaleźć sposób, aby to działa prawidłowo przy użyciu iOS 8 na iPhone 6.
Barry Beerman
2
To samo dla mnie z iOS8.1 wersja ostateczna
fvisticot
4
Nadal obecny w IOS 9
Wielebny
45

Walczyłem z tym problemem przez kilka godzin, przeczytałem każdy odpowiedni temat i dowiedziałem się, że błąd został spowodowany, ponieważ w ustawieniach prywatności mojego urządzenia dostęp kamery do mojej aplikacji został zablokowany !!! Nigdy nie odmawiałem dostępu do kamery i nie wiem, jak została zablokowana, ale to był problem!

Pantelis Proios
źródło
4
nie jestem pewien, czy to faktycznie działało dla ciebie, ale dla mnie nie działało. Mam tylko nadzieję, że @KevinH ma rację.
Deepak Thakur
4
Nie, dostęp do kamery jest w moim przypadku włączony dla tej aplikacji. Ale wierzę, że może to być spowodowane, choć pośrednio, przez ustawienia: zmiany w ustawieniach czasami nie wchodzą w życie natychmiast, ktoś w cupertino musiał zoptymalizować połączenie, aby gdzieś zsynchronizować
Anton Tropashko
Ta sugestia rozwiązała dla mnie problem. Wcześniej dotknąłem opcji „Nie zezwalaj”, gdy selektor kamery pojawił się w mojej aplikacji. Myślałem, że zapyta mnie za każdym razem, gdy wchodzę do kamery, ale tak nie było. Musiałem przejść do Ustawienia> Prywatność> Aparat i włączyć suwak dla mojej aplikacji. Potem działało poprawnie. Wydaje się trochę głupie ze strony Apple'a, że ​​nie pyta za każdym razem ...
John Contarino,
dokładnie czasami nie możemy myśleć o problemie podniesionym dla tego rodzaju błędów. dzięki kolego bardzo pomocny
Mr.Javed Multani
Najlepszą opcją jest przed użyciem aparatu do wykrycia, czy funkcja jest aktywna, a jeśli nie, ostrzeż użytkownika, że ​​robienie zdjęć jest niedostępne, dopóki aparat nie zostanie włączony w ustawieniach. W systemie iOS 10 można wysłać użytkownika do określonych ustawień aplikacji (było to możliwe przed iOS 8, ale nie było możliwe w iOS 8 i 9, jeśli dobrze pamiętam).
kindaian
33

Nie mam wystarczającej liczby punktów reputacji, aby skomentować powyższą odpowiedź @ greg, dlatego dodam tutaj moje spostrzeżenia. Mam projekt Swift na iPada i iPhone'a. Mam metodę w moim głównym kontrolerze widoku (odpowiedni bit poniżej). Kiedy testuję to na telefonie, wszystko działa poprawnie i nie są generowane żadne ostrzeżenia. Kiedy uruchamiam go na iPadzie, wszystko działa poprawnie, ale widzę ostrzeżenie o migawce widoku. Ciekawe jest jednak to, że kiedy uruchamiam na iPadzie bez użycia kontrolera popover, wszystko działa poprawnie bez ostrzeżenia. Niestety, Apple nakazuje, aby próbnik obrazu był używany w oknie popover na iPadzie, jeśli aparat nie jest używany.

    dispatch_async(dispatch_get_main_queue(), {
        let imagePicker: UIImagePickerController = UIImagePickerController();
        imagePicker.sourceType = UIImagePickerControllerSourceType.SavedPhotosAlbum;
        imagePicker.mediaTypes = [kUTTypeImage];
        imagePicker.allowsEditing = false;
        imagePicker.delegate = self;

        if(UIDevice.currentDevice().userInterfaceIdiom == .Pad){ // on a tablet, the image picker is supposed to be in a popover
            let popRect: CGRect = buttonRect;
            let popover: UIPopoverController = UIPopoverController(contentViewController: imagePicker);
            popover.presentPopoverFromRect(popRect, inView: self.view, permittedArrowDirections: UIPopoverArrowDirection.Up, animated: true);
        }else{
            self.presentViewController(imagePicker, animated: true, completion: nil);
        }
    });
dlw
źródło
Wygląda na to, że jest to poprawna sugestia, ponieważ mam ten komunikat o błędzie nawet w systemie iOS 9.0.2. Mam tylko aplikację na iPhone'a i kiedy uruchamiam ją na iPadzie Mini, widzę ten komunikat podczas prezentacji selektora obrazów. Z jakiegoś powodu iOS uważa, że ​​uruchamiam aplikację na iPada.
John Tracid,
16

Natknąłem się na to po wywołaniu UIImagePickerController presentViewController: od wywołania zwrotnego do delegata UIAlertView. Rozwiązałem problem, wypychając presentViewController: wywołaj bieżące śledzenie wykonania przy użyciu dispatch_async.

- (void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex
{
    dispatch_async(dispatch_get_main_queue(), ^{
        UIImagePickerController *imagePickerController = [[UIImagePickerController alloc] init];
        imagePickerController.delegate = self;

        if (buttonIndex == 1)
            imagePickerController.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
        else
            imagePickerController.sourceType = UIImagePickerControllerSourceTypeCamera;

        [self presentViewController: imagePickerController
                           animated: YES
                         completion: nil];
    });
}
greg
źródło
To właśnie dla mnie to rozwiązało. Próbowałem przedstawić UIImagePickerController z wnętrza bloku akcji UIAlertAction.
josefdlange
alertView został uznany za przestarzały, czy zadziałałoby, jeśli zamiast tego użyję asynchronizacji w akcji UIAlertViewController?
DrPatience
@DrPatience Pewnie. dispatch_async działa w dowolnym miejscu. Nie wiem, czy jest to konieczne (zależy od twojego kodu). Czytaj dalej na GCD - ma wiele zastosowań.
greg
12

Miałem ten problem podczas animowania niektórych widoków, a aplikacja przechodziła w tryb tła i wracała. Poradziłem sobie z tym ustawiając flagę na Aktywną. Ustawiłem na NIE

- (void)applicationWillResignActive:(UIApplication *)application

i TAK w

- (void)applicationDidBecomeActive:(UIApplication *)application

i odpowiednio animuj lub nie animuj moich poglądów. Zajęłam się tym problemem.

byedissident
źródło
11

Miałem to z UIAlertControllerStyleActionSheet dając użytkownikowi opcję zrobienia zdjęcia aparatem lub skorzystania z biblioteki.

Próbowałem symbolicznego punktu przerwania w komunikacie o błędzie wprowadź opis zdjęcia tutaj

To pokazało mi, że błąd jest generowany przez wewnętrzne użycie UICollectionView podczas prezentacji

[self presentViewController:alert animated:YES completion:nil];

wprowadź opis zdjęcia tutaj

Naprawiłem to poprzez szybkie ustawienie ramki przed prezentacją

[alert setPreferredContentSize: alert.view.frame.size];

Oto pełna metoda działająca bez błędu

-(void)showImageSourceAlertFromSender:(id)sender{
UIButton *senderButton = (UIButton*)sender;
UIAlertController *alert = [UIAlertController alertControllerWithTitle:nil message:nil preferredStyle:UIAlertControllerStyleActionSheet];
UIAlertAction *cameraAction = [UIAlertAction actionWithTitle:@"Camera" style:UIAlertActionStyleDefault
                                                     handler:^(UIAlertAction *action) {
                                                         [self takePhoto];
                                                     }];
UIAlertAction *libraryAction = [UIAlertAction actionWithTitle:@"Library" style:UIAlertActionStyleDefault
                                                      handler:^(UIAlertAction *action) {
                                                          [self selectPhotoFromLibraryFromSender:sender];
                                                      }];
[alert addAction:cameraAction];
[alert addAction:libraryAction];
alert.popoverPresentationController.delegate = self;
alert.popoverPresentationController.sourceRect = senderButton.frame;
alert.popoverPresentationController.sourceView = self.view;

[alert setPreferredContentSize: alert.view.frame.size];

[self presentViewController:alert animated:YES completion:^(){
}];}
Tak
źródło
10

Można wyciszyć ostrzeżenie „Migawka widoku”, odwołując się do viewwłaściwości przed przedstawieniem kontrolera widoku. Spowoduje to załadowanie widoku i umożliwi iOS renderowanie go przed zrobieniem migawki.

UIAlertController *controller = [UIAlertController alertControllerWithTitle:nil message:nil preferredStyle:UIAlertControllerStyleActionSheet];
controller.modalPresentationStyle = UIModalPresentationPopover;
controller.popoverPresentationController.barButtonItem = (UIBarButtonItem *)sender;

... setup the UIAlertController ... 

[controller view]; // <--- Add to silence the warning.

[self presentViewController:controller animated:YES completion:nil];
Steve Shepard
źródło
To prawie niezwykle przydatna wskazówka. Dziękuję Ci!!!! (W moim przypadku wciąż
pojawia
Jednak gdy dodam cameraOverlayView, niestety nadal mam ten problem, nawet gdy zastosuję tę wskazówkę.
Fattie
8

Dla każdego, kto widzi problem z czarnym podglądem po przechwyceniu obrazu, ukrywanie paska stanu po wyświetleniu UIPickerController wydaje się rozwiązać ten problem.

UIImagePickerControllerSourceType source = [UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera] ? UIImagePickerControllerSourceTypeCamera : UIImagePickerControllerSourceTypeSavedPhotosAlbum;
UIImagePickerController *cameraController = [[UIImagePickerController alloc] init];
        cameraController.delegate = self;
        cameraController.sourceType = source;
        cameraController.allowsEditing = YES;
        [self presentViewController:cameraController animated:YES completion:^{
            //iOS 8 bug.  the status bar will sometimes not be hidden after the camera is displayed, which causes the preview after an image is captured to be black
            if (source == UIImagePickerControllerSourceTypeCamera) {
                [[UIApplication sharedApplication] setStatusBarHidden:YES withAnimation:UIStatusBarAnimationNone];
            }
        }];
Dan
źródło
1
całkowicie uratowałem mój dzień! Próbowałem powyższych metod, żadne nie działało. i to zadziałało
Stan
Rozwiązanie nie działa. Myślę, że kiedy przechwytujemy obraz w tym czasie StatusBar jest już ukryty.
Mihir Oza,
5

Znalazłem ten sam problem i próbowałem wszystkiego. Mam dwie różne aplikacje, jedną w celu C i drugą w trybie szybkim - oba mają ten sam problem. Komunikat o błędzie pojawia się w debuggerze, a ekran robi się czarny po pierwszym zdjęciu. Dzieje się tak tylko w iOS> = 8.0, oczywiście jest to błąd.

Znalazłem trudne obejście. Wyłącz sterowanie kamerą za pomocą imagePicker.showsCameraControls = false i utwórz własną nakładkę z brakującymi przyciskami. Istnieją różne samouczki dotyczące tego, jak to zrobić. Dziwny komunikat o błędzie pozostaje, ale przynajmniej ekran nie robi się czarny i masz działającą aplikację.

Thomas Zimmer
źródło
Miałem dokładnie taki sam problem jak ty, zobacz moją odpowiedź poniżej.
Dan
5

Może to być błąd wbudowanego ImagePickerController. Mój kod działa, ale czasami ulega awarii na telefonie iPhone 6 Plus.

Wypróbowałem wszystkie rozwiązania sugerowane przez inne odpowiedzi, ale nie miałem szczęścia. Problem ostatecznie rozwiązany po przejściu na JPSImagePickerController .

JonSlowCN
źródło
3

Próbowałem już wszystkiego, mój problem polegał na tym, że próbnik obrazów do aparatu i biblioteki zdjęć zniknął zaraz po ich wyświetleniu. Rozwiązałem to następującą linią (szybkie)

imagePicker.modalPresentationStyle = UIModalPresentationStyle.OverCurrentContext
Waffeln
źródło
3

Jestem prawie pewien, że to tylko błąd w iOS 8.0. Jest odtwarzalny z najprostszymi aplikacjami POC, które nie robią nic więcej, jak tylko próbują zaprezentować UIImagePickerController tak, jak robisz to powyżej. Co więcej, według mojej wiedzy nie ma alternatywnego wzorca wyświetlania selektora / kamery obrazu. Możesz nawet pobrać przykładową aplikację Apple Using UIImagePickerController, uruchomić ją, a ona wygeneruje ten sam błąd po wyjęciu z pudełka.

To powiedziawszy, funkcjonalność nadal działa dla mnie. Czy oprócz ostrzeżenia / błędu masz problemy z działaniem aplikacji?

Gaurav Patel
źródło
3

Jeśli używamy UIImagePickerControllerjako jako właściwości, to ostrzeżenie zniknie.Załóżmy, że nie używamy wyniku z UIImagePickerController, jeśli tworzymy instancję UIImagePickerControllerwewnątrz funkcji.

Antony Ouseph
źródło
2

Wywołanie tej metody działało dla mnie. Umieść go po przedstawieniu swojego widoku.

[yourViewBeingPresented.view layoutIfNeeded];
Konstabl
źródło
1

Mam również ten sam problem i rozwiązałem go, sprawdzając, czy kamera jest dostępna:

BOOL cameraAvailableFlag = [UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera];
    if (cameraAvailableFlag)
        [self performSelector:@selector(showcamera) withObject:nil afterDelay:0.3];
aftab muhammed khan
źródło
1
isSourceTypeAvailable zwraca true, mimo że odmówiłem dostępu do kamery mojej aplikacji. Wyświetlacz jest pusty, jeśli dostęp do kamery jest zabroniony.
Καrτhικ
1

Natknąłem się na ten problem. Kiedy wywołujemy aparat i udostępniamy widoki spowodowały ten problem. Na przykład zadzwoń do kamery i ustaw widok zero w metodzie viewDidDisappear, ten błąd wystąpi, ponieważ nie ma wywołania zwrotnego dla zdarzenia kamery. Upewnij się również o tym przypadku dla tego błędu.

Gobi M.
źródło
1

Mam ten sam błąd, otrzymuję poniżej komunikat w konsoli podczas otwierania aparatu.

„Migawka widoku, który nie został zrenderowany, powoduje powstanie pustej migawki. Upewnij się, że widok został zrenderowany co najmniej raz przed migawką lub migawką po aktualizacji ekranu. ”

Dla mnie problem polegał na wyświetleniu nazwy pakietu w pliku Info.plist. W pewnym sensie był pusty, umieściłem tam nazwę mojej aplikacji i teraz działa dobrze. Nie otrzymałem żadnego powiadomienia o pozwoleniu na aparat z powodu pustej nazwy wyświetlanej pakietu. It zablokował renderowanie widoku.

problem nie dotyczył widoku, ale przedstawiając go bez pozwolenia. możesz to sprawdzić w ustawieniach -> prywatność -> Aparat, jeśli Twojej aplikacji nie ma na liście, problem może być taki sam.

Shabeer Ali
źródło
1

Korzystam z Phonegap, ale ten wątek pojawia się jako pierwszy, gdy Googling wyświetla komunikat o błędzie.

Dla mnie ten problem zniknął, definiując typ obrazu w formacie PNG.

encodingType : Camera.EncodingType.PNG

Cała linia jest:

 navigator.camera.getPicture(successFunction, failFunction, { encodingType : Camera.EncodingType.PNG, correctOrientation:true, sourceType : Camera.PictureSourceType    .PHOTOLIBRARY, quality: 70, allowEdit : false , destinationType: Camera.DestinationType.DATA_URL});

Twój przebieg może się różnić, ale to załatwiło sprawę.

Jannunen
źródło
1

Możesz też rozważyć użycie drawViewHierarchyInRect:

Szybki:

extension UIImage{

    class func renderUIViewToImage(viewToBeRendered: UIView) -> UIImage
    {
        UIGraphicsBeginImageContextWithOptions(viewToBeRendered.bounds.size, true, 0.0)
        viewToBeRendered.drawViewHierarchyInRect(viewToBeRendered.bounds, afterScreenUpdates: true)
        viewToBeRendered.layer.renderInContext(UIGraphicsGetCurrentContext()!)

        let finalImage = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()

        return finalImage
    }
}

Cel C:

- (UIImage *)snapshot:(UIView *)view
{
    UIGraphicsBeginImageContextWithOptions(view.bounds.size, YES, 0);
    [view drawViewHierarchyInRect:view.bounds afterScreenUpdates:YES];
    UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    return image;
}

Zobacz także:

Eric
źródło
0

W moim przypadku (XCode 7 i iOS 9) używam UINavigationController„ukrytego”, więc muszę dodaćUINavigationControllerDelegate do obecnej kamery lub rolki i działa tak, jak powinno! And pickerControllerDelegate.selfteż nie wyświetla błędu!

Daniel Arantes Loverde
źródło