Błąd UIImagePickerController: tworzenie migawek widoku, który nie został wyrenderowany, powoduje powstanie pustej migawki w systemie iOS 7

103

Ten błąd pojawia się tylko w iOS 7 i aplikacja uległa awarii. W iOS 6 nigdy nie pojawia się żaden błąd, tylko raz ostrzeżenie o pamięci przy otwieraniu aparatu.

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.

Oto co robię.

imagePicker = [[UIImagePickerController alloc] init];
[imagePicker setDelegate:self];
[imagePicker setSourceType:UIImagePickerControllerSourceTypeCamera];
[imagePicker setAllowsEditing:YES];

[self presentModalViewController:imagePicker animated:YES];

Próbowałem opóźnić presentModalViewController, ale nadal otrzymuję tę samą wiadomość. Po kilku sekundach (7-10) aplikacja uległa awarii.

Ten błąd występuje tylko w iOS 7.

Czy ktoś ma wskazówkę?

Didats Triadi
źródło
3
Mam ten sam problem. W systemie iOS7 UIIMagePickerController już nie działa.
condor304,
Nazywanie tej metody działało dla mnie. Umieść go po przedstawieniu swojego widoku. [yourViewBeingPresented.view layoutIfNeeded];
Bobby

Odpowiedzi:

32

Problem w iOS7 dotyczy przejść. Wygląda na to, że jeśli poprzednie przejście nie zostało zakończone i uruchomisz nowe, iOS7 psuje widoki, gdzie iOS6 wydaje się zarządzać nim poprawnie.

Powinieneś zainicjować kamerę w swoim UIViewController, dopiero po załadowaniu widoku i po upływie limitu czasu:

- (void)viewDidAppear:(BOOL)animated 
{
    [super viewDidAppear:animated];
    //show camera...
    if (!hasLoadedCamera)
        [self performSelector:@selector(showcamera) withObject:nil afterDelay:0.3];
}

a oto kod inicjalizacyjny

- (void)showcamera {
    imagePicker = [[UIImagePickerController alloc] init];
    [imagePicker setDelegate:self];
    [imagePicker setSourceType:UIImagePickerControllerSourceTypeCamera];
    [imagePicker setAllowsEditing:YES];

    [self presentModalViewController:imagePicker animated:YES];
}
Lefteris
źródło
1
Jak dotąd to wydaje się działać, przetestowałem to, robiąc 10 zdjęć jedno po drugim bez problemu.
DevC,
3
PresentModalViewController został uznany za przestarzały w iOS 6. Sugeruje się, aby teraz używać presentViewController.
Gallymon
5
Ten sam problem i poprawka dla iOS8.
Yauheni Shauchenka
1
Próbuję, aby to działało z UIAertControl - jedną opcją jest przedstawienie selektora obrazów dla przeglądarki zdjęć - to działa dobrze, a drugą jest prezentacja dla kamery - to nie działa. Gdzie mógłbym zbudować opóźnienie podczas używania a UIALertController?
SimonTheDiver
3
Nie inicjuję kamery w viewDidAppear / Load. Mam widok tabeli i włączam kamerę w odpowiedzi na jedną z opcji widoku tabeli. I otrzymuję ten komunikat o błędzie. Jakieś pomysły?
Henning
18

Ten błąd pojawił się również w przypadku przykładowego projektu kodu Apple PhotoPicker.

Używałem Xcode w wersji 5.0 i iOS 7.0.3 na iPhonie 4.

Kroki ku reprodukcji:

  1. Pobierz przykładowy projekt Apple PhotoPicker ze strony https://developer.apple.com/library/ios/samplecode/PhotoPicker/Introduction/Intro.html

  2. W APLViewController.m skomentuj wiersz 125

    //imagePickerController.showsCameraControls = NO;

  3. W APLViewController.m zakomentuj linie 130-133

    //[[NSBundle mainBundle] loadNibNamed:@"OverlayView" owner:self options:nil];
    // self.overlayView.frame = imagePickerController.cameraOverlayView.frame;
    // imagePickerController.cameraOverlayView = self.overlayView;
    // self.overlayView = nil;

  4. Zbuduj i uruchom aplikację.

  5. Po uruchomieniu obróć urządzenie do trybu poziomego.

  6. Kliknij ikonę aparatu, aby otworzyć UIImagePickerController w trybie aparatu.

  7. Wyświetl dane wyjściowe konsoli.

Wyjście konsoli

PhotoPicker [240: 60b] Wykonanie migawki widoku, który nie został wyrenderowany, powoduje powstanie pustej migawki. Upewnij się, że widok został wyrenderowany co najmniej raz przed utworzeniem migawki lub migawki po aktualizacji ekranu.

showsCameraControls

Problem występuje u mnie, gdy ma to wartość TAK (domyślnie).

Ustawienie tej opcji na NIE wyeliminowało komunikat.

Zgłoszenie błędu

Właśnie złożyłem raport o błędzie w Apple.

Wypróbowałem wiele sugestii zawartych w różnych postach, ale nie znalazłem satysfakcjonującego obejścia.

Scott Carter
źródło
1
Jak Apple ci odpowiedział? Mam ten sam problem i rozwiązania w stackoverflow nie działają.
heekyu
Nie słyszałem jeszcze o tym od Apple. Napiszę odpowiedź, jeśli otrzymam od nich odpowiedź.
Scott Carter
Jakieś wieści od Apple? @ScottCarter
Benjamin Toueg
1
Właśnie sprawdziłem ponownie. Brak działań w związku z otwartym błędem, odkąd został zgłoszony 2 listopada 2013 r.
Scott Carter
To jest błąd 15377241 na bugreport.apple.com
Scott Carter
11

Pojawił się problem, gdy próbowałem pokazać widok z kamery wewnątrz popovera. Pod iOS6 to nie był problem, ale w iOS7 dostałem wiadomość

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.

także.

Jednak po zmianie prezentacji widoku aparatu na pełny ekran, jak opisano w sekcji Robienie zdjęć i filmów, Biblioteka programistów iOS, wszystko znowu poszło dobrze i komunikat nigdy się więcej nie pojawił. Musiałem jednak upewnić się, że w zależności od tego, w jakim trybie jest aplikacja (tj. Prezentując widok z kamery lub rolkę ze zdjęciami), musiałem albo odrzucać popover, albo kontroler widoku przy każdym - (void) imagePickerControllerDidCancel: (UIImagePickerController *) pickerwywołaniu metody .

Arne
źródło
3
cameraUI.modalPresentationStyle = UIModalPresentationFullScreen; pracuje dla mnie. To jedyna rzecz, która odniosła tu sukces. Dzięki!
daveMac
2
Wreszcie! Miałem ten problem wiele razy i nigdy nie znalazłem dobrego rozwiązania. Poczuj się tak głupio, że nigdy nie zaglądasz dalej w wątkach z pytaniami - imagePicker.modalPresentationStyle = UIModalPresentationFullScreen; rozwiązał to dla mnie. To powinna być akceptowana odpowiedź :)
woobione
6

stworzyć nieruchomość

@property (nonatomic) UIImagePickerController *imagePickerController;

Następnie

UIImagePickerController *picker = [[UIImagePickerController alloc] init];
picker.delegate = self;
picker.modalPresentationStyle = UIModalPresentationCurrentContext;
picker.sourceType = UIImagePickerControllerSourceTypeCamera;
picker.allowsEditing = YES;
self.imagePickerController = picker;
[self presentViewController:self.imagePickerController animated:YES completion:nil];

To powinno rozwiązać problem

Asfanur
źródło
3
picker.modalPresentationStyle = UIModalPresentationCurrentContext; zrobił różnicę dla mnie.
Pan Berna,
1
Działa przy pierwszym wyświetleniu selektora, ale potem pojawia się ostrzeżenie.
daveMac
potwierdzam picker.modalPresentationStyle = UIModalPresentationCurrentContext; Rozwiązuje dla mnie problem nieprawidłowych układów w iOS 8
João Nunes
Nie działa dla mnie - dodano to do akcji UIButton na iOS 8.1.3
Andy,
Wydawało się to obiecujące, ale nic nie pomogło w kwestii migawek ORAZ po zrobieniu zdjęcia wyświetlono bezużyteczną ramkę wokół części obrazu.
zwrócił ..
4

Użyłem tego kodu, aby obejść problem:

UIImagePickerController *imagePicker = [[UIImagePickerController alloc] init];
[imagePicker setSourceType:UIImagePickerControllerSourceTypeCamera];
[imagePicker setDelegate:self];

if ([self respondsToSelector:@selector(presentViewController:animated:completion:)]){
    [imagePicker setShowsCameraControls:NO];
    [self presentViewController:imagePicker animated:YES completion:^{
        [imagePicker setShowsCameraControls:YES];
    }];
} else {
    [imagePicker setShowsCameraControls:YES];
    [self presentModalViewController:imagePicker animated:YES];
}
Germán Marquès
źródło
1
Chociaż pomysł działa w teorii, niestety pokazane elementy sterujące nie działają lub wyglądają poprawnie.
daveMac
I nie pozbyło się również ostrzeżenia (przynajmniej dla mnie)
Ege Akpinar
3

Mam ten sam problem i znalazłem rozwiązanie. Myślę, że to błąd związany z orientacją Twojej aplikacji. Moja aplikacja używa tylko trybu poziomego, ale UIImagePickerController używa trybu pionowego. Dodaję blok try-catch do main.m i otrzymuję prawdziwy wyjątek:

Supported orientations has no common orientation with the application, and shouldAutorotate is returning YES

Jak rozwiązać ten problem:

1) Ponownie sprawdź orientację urządzenia w pliku Target-> General lub .plist: Obsługiwane orientacje interfejsu: Pozioma lewa, Pozioma prawa.

2) Dodaj w AppDelegate.m:

- (NSUInteger)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window {
    return UIInterfaceOrientationMaskLandscape | UIInterfaceOrientationMaskPortrait;
}

Po tym kroku UIImagePickerController działa poprawnie, ale moje kontrolery widoku można obrócić do trybu portretowego. Aby rozwiązać ten problem:

3) Utwórz kategorię dla UINavigationController, (supportedInterfaceOrientations przeniesione z UIViewController do UINavigationController w iOS6):

@implementation UINavigationController (RotationIOS6)

- (NSUInteger)supportedInterfaceOrientations {
    return UIInterfaceOrientationMaskLandscape;
}

@end

To rozwiązanie działa poprawnie na iOS 6.0, 6.1, 7.0. Mam nadzieję że to pomoże.

Roman Ermolov
źródło
1
Naprawiam aplikację w trybie portretowym, która wyświetla błąd wspomniany w OP. Wydawałoby się więc, że Twoje rozwiązanie nie ma uniwersalnego zastosowania.
JohnK
Czy próbowałeś dodać blok try-catch do main.m i wypisać wyjątek i stacktrace?
Roman Ermolov
Jak to ?
JohnK
@JohnK tak, w ten sposób.
Roman Ermolov
3

Ten błąd pojawia się podczas tworzenia aplikacji za pomocą zestawu iOS SDK 6.1, docelowego wdrożenia systemu iOS 6.1 i uruchamiania aplikacji na telefonie iPhone z systemem iOS 7. Aplikacja nie ulega awarii, ale UIViewController shouldAutorotatemetoda implementacji pomaga mi usunąć komunikat o błędzie.

- (BOOL)shouldAutorotate {
    return YES;
}
Grigori A.
źródło
3

Miałem ten sam problem, gdy próbowałem zmodyfikować aplikację demonstracyjną dostarczaną z Avirary SDK , w aplikacji demonstracyjnej można edytować tylko zdjęcie wybrane z rolki aparatu. Aby spróbować edytować zdjęcie przez przechwytywanie z aparatu, najpierw dodałem następujący kod w pliku UIViewcontroller.m:

#pragma mark - Take Picture from Camera
- (void)showCamera
{
//[self launchPhotoEditorWithImage:sampleImage highResolutionImage:nil];

    if ([self hasValidAPIKey]) {
        UIImagePickerController * imagePicker = [UIImagePickerController new];
        [imagePicker setSourceType:UIImagePickerControllerSourceTypeCamera];
        [imagePicker setDelegate:self];
        [imagePicker setAllowsEditing:YES]; //important, must have

        if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone) {
            [self presentViewController:imagePicker animated:YES completion:nil];
        }else{
            [self presentViewControllerInPopover:imagePicker];
        }
    }
}

Po uruchomieniu aplikacji pojawił się błąd:

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.

Aby rozwiązać ten błąd, zmodyfikuj delegata UIImagePicker w pliku UIViewContooler.m, jak pokazano poniżej:

#pragma mark - UIImagePicker Delegate

- (void) imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{
    NSURL * assetURL = [info objectForKey:UIImagePickerControllerReferenceURL];

    void(^completion)(void)  = ^(void){

        [[self assetLibrary] assetForURL:assetURL resultBlock:^(ALAsset *asset) {
            if (asset){
                [self launchEditorWithAsset:asset];
            }
        } failureBlock:^(NSError *error) {
            [[[UIAlertView alloc] initWithTitle:@"Error" message:@"Please enable access to your device's photos." delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil] show];
        }];

        UIImage * editedImage = [info objectForKey:UIImagePickerControllerEditedImage];
        if(editedImage){
            [self launchPhotoEditorWithImage:editedImage highResolutionImage:editedImage];
        }

    };

    if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone) {
        [self dismissViewControllerAnimated:YES completion:completion];
    }else{
        [self dismissPopoverWithCompletion:completion];
    }

}    

Wtedy błąd zniknął i aplikacja działa!

Tony
źródło
1

Spróbuj tego, użyj

[self performSelector:@selector(presentCameraView) withObject:nil afterDelay:1.0f];

i funkcji

-(void)presentCameraView{
    [self presentViewController:imagePicker animated:YES completion:nil];
}

zamienić. [self presentModalViewController:imagePicker animated:YES]; i przyczyny imagePickerjako zmienna globalna.

JerryZhou
źródło
1

To właśnie rozwiązało problem w mojej aplikacji ymmv

po pierwsze jest to aplikacja na iPhone'a - iPada

w appname-Info.plist. w Obsługiwanych orientacjach interfejsu (iPad) pokazał 4 orientacje.

w Obsługiwanych orientacjach interfejsu pokazał 3 orientacje. Dodałem czwartą i uruchomiłem aplikację, bez wyjścia debugowania.

Mam nadzieję że to pomoże.

user1045302
źródło
0

Właśnie napotkałem ten sam problem. W moim przypadku problem polegał na tym, że miałem kod spoza ARC i przeniosłem go do ARC. Kiedy przeprowadzałem migrację, nie miałem silnego odniesienia do programu UIImagePickerControlleri to było przyczyną awarii.

Mam nadzieję, że to pomoże :)

arturgrigor
źródło
0

Miałem ten sam problem w iOS 8, ale dostęp do aparatu był wyłączony w Ustawieniach -> Prywatność dla mojej aplikacji. Po prostu włączyłem to i działało.

BhushanVU
źródło
0

Spędziłem dużo czasu próbując znaleźć rozwiązanie i, co zaskakujące, znalazłem je na końcu i było to bardzo zabawne, gdy je odkryłem.

Oto, co zrobisz, aby odzyskać wybrany obraz i wznowić pracę :)

-(void)imagePickerController:(UIImagePickerController*)picker didFinishPickingMediaWithInfo:(NSDictionary*)info
{
    UIImage* pickedImage = [info objectForKey:@"UIImagePickerControllerOriginalImage"];
    [composeImageView setImage:pickedImage];
[picker dismissViewControllerAnimated:YES completion:nil];
 }

Tak, aby rozwiązać ten problem, wystarczy normalnie odrzucić selektor, tak jak wygląda ten komunikat: „Tworzenie migawki widoku, który nie został wyrenderowany, powoduje powstanie pustej migawki. Upewnij się, że widok został wyrenderowany przynajmniej raz przed wykonaniem zrzutu lub migawki po aktualizacje ekranu ”. powstrzymuje selektor przed odpowiadaniem, ale możesz go odrzucić i normalnie odzyskać obraz.

DevSherif
źródło
0

W moim przypadku było to związane ze zmianą layoutu: VC prezentujący UIImagePickerViewControllerma ukryty pasek stanu, ale UIImagePickerViewControllernie.

Więc rozwiązałem to, ukrywając pasek stanu w UIImagePickerViewControllertak, jak pokazano w tej odpowiedzi .

kanobius
źródło
-1

Nie odpowiadając bezpośrednio na twoje pytanie, ale wspomniałeś, że masz ostrzeżenie dotyczące pamięci, być może przechowujesz nieprzetworzony obraz we właściwości, która może prowadzić do ostrzeżenia dotyczącego pamięci. Dzieje się tak, ponieważ nieprzetworzony obraz zajmuje około 30 MB pamięci. Zauważyłem podobne ostrzeżenie dotyczące pamięci podczas testowania aplikacji na iOS6, które były na serii iPhone 4. Nadal otrzymuję to ostrzeżenie, gdy urządzenia zostały zaktualizowane do iOS7. Nie ma ostrzeżenia dotyczącego pamięci podczas testowania na telefonie iPhone 5 z systemem iOS7.

DevC
źródło
-5

Wymiana pieniędzy

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

do

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

naprawił problem dla mnie.

Yuki
źródło