iOS 8 Un instantané d'une vue qui n'a pas été rendue entraîne un instantané vide

228

Dans iOS 8, je rencontre des problèmes pour capturer des images à partir de l'appareil photo.

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

Mais dans iOS 8, je reçois ceci:

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.

J'ai essayé avec la solution fournie par This Post avec

@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];

et ça

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

et ça

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];
});

et ça

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

et ça

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

}];

une idée?

souvickcse
la source
3
Avoir le même problème et plus encore, ce bug plante de temps en temps mon application. J'espère que la mise à jour 8.0.2 corrigera ce bogue. Lorsque je lance mon application dans iOS7, cela fonctionne comme un charme sans aucun avertissement stupide. On dirait que iOS 8 a le long chemin de la stabilité.
NCFUSN
9
Événement avec la mise à jour 8.0.2, ce problème persiste
ArdenDev
2
J'avais le même problème. Après avoir pris la photo, je faisais du traitement dans un autre fil. Après avoir déplacé le code vers le thread principal, tout s'est bien passé. C'est-à-dire que mon code avant était: dispatch_async(dispatch_get_main_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{que j'ai changé endispatch_async(dispatch_get_main_queue(), ^{
mikeyq6
9
Le même problème se produit dans iOS 8.1
Raptor
12
Cela se produit également dans iOS 9.
Sebyddd

Réponses:

131

Je suis sûr que ce n'est qu'un bug dans iOS 8.0. Il est reproductible avec la plus simple des applications POC qui ne fait rien d'autre que d'essayer de présenter ce UIImagePickerControllerque vous faites ci-dessus. De plus, il n'y a pas de modèle alternatif à l'affichage du sélecteur d'image / caméra, à ma connaissance. Vous pouvez même télécharger l' exemple d'application Apple utilisant UIImagePickerController , l'exécuter et cela générera la même erreur hors de la boîte.

Cela dit, la fonctionnalité fonctionne toujours pour moi. Outre l'avertissement / l'erreur, avez-vous des problèmes avec le fonctionnement de votre application?

KevinH
la source
2
Oui, c'est probablement un bogue, le code fonctionne aussi très bien pour moi.
souvickcse
4
@souvickcse Je rencontre également cette erreur. Chaque fois que cela se produit, l'aperçu de l'image qui apparaît une fois qu'une nouvelle photo a été prise est complètement noir. Cependant, les boutons "Re-Take" et "Use Photo" au bas de l'écran apparaissent et fonctionnent toujours correctement. Êtes-vous témoin de ce même comportement?
Barry Beerman,
3
@souvickcse J'utilise la dernière ligne de base du plug-in de la caméra phonegap située ici: github.com/apache/cordova-plugin-camera . Tout fonctionne bien avec iOS 7.1 fonctionnant sur un iPhone 5 mais je ne trouve pas de moyen de le faire fonctionner correctement en utilisant iOS 8 sur un iPhone 6.
Barry Beerman
2
La même chose pour moi avec iOS8.1 final
fvisticot
4
Toujours présent dans IOS 9
le révérend
45

J'ai eu des problèmes avec ce problème pendant plusieurs heures, j'ai lu tous les sujets pertinents et j'ai découvert que l'erreur était due au fait que sous les paramètres de confidentialité de mon appareil, l'accès de la caméra à mon application était bloqué !!! Je n'ai jamais refusé l'accès à la caméra et je ne sais pas comment elle a été bloquée mais c'était le problème!

Pantelis Proios
la source
4
Je ne sais pas si cela a vraiment fonctionné pour vous, mais cela n'a pas fonctionné pour moi. J'espère juste que @KevinH est correct.
Deepak Thakur
4
Non, l'accès à la caméra est activé pour cette application dans mon cas. Mais je crois que cela pourrait être causé, bien qu'indirectement, par des paramètres: les modifications apportées aux paramètres ne prennent pas parfois effet immédiatement, quelqu'un à cupertino doit avoir optimisé un appel pour se synchroniser quelque part
Anton Tropashko
Cette suggestion a résolu le problème pour moi. J'avais précédemment touché "Ne pas autoriser" lorsque le sélecteur de caméra est apparu dans mon application. Je pensais que cela me serait demandé à chaque fois que j'accéderais à la caméra, mais ce n'était pas le cas. J'ai dû aller dans Paramètres> Confidentialité> Appareil photo et activer le curseur de mon application. Ensuite, cela a fonctionné correctement. Semble sorta idiot de la part d'Apple de ne pas demander à chaque fois ...
John Contarino
exactement, parfois, nous ne pouvons pas penser que le problème soulevé pour ce type d'erreurs. thx buddy très utile
Mr.Javed Multani
La meilleure option est avant d'utiliser l'appareil photo pour détecter si la fonction est active, et sinon, avertir l'utilisateur que la prise de photos n'est pas disponible jusqu'à ce que l'appareil photo soit activé sur les paramètres. Sur iOS 10, il est possible d'envoyer l'utilisateur aux paramètres d'application spécifiques (c'était possible avant iOS 8, mais pas possible dans iOS 8 et 9, si je me souviens bien).
2017
33

Je n'ai pas assez de points de réputation pour commenter la réponse de @ greg ci-dessus, alors ajoutez mes observations ici. J'ai un projet Swift pour iPad et iPhone. J'ai une méthode à l'intérieur de mon contrôleur de vue principal (bit pertinent ci-dessous). Lorsque je teste cela sur un téléphone, tout fonctionne correctement et aucun avertissement n'est généré. Lorsque je l'exécute sur un iPad, tout fonctionne correctement, mais je vois l'avertissement concernant la capture instantanée de la vue. Cependant, le fait intéressant est que lorsque je cours sur un iPad sans utiliser le contrôleur popover, tout fonctionne correctement sans avertissement. Malheureusement, Apple exige que le sélecteur d'image soit utilisé dans un popover sur iPad, si l'appareil photo n'est pas utilisé.

    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
la source
On dirait que c'est une suggestion correcte car je reçois ce message d'erreur même avec iOS 9.0.2. Je n'ai qu'une application iPhone et lorsque je l'exécute sur mon iPad Mini, je vois ce message lorsque je présente le sélecteur d'images. Pour une raison quelconque, iOS pense que je lance l'application iPad.
John Tracid
16

J'ai rencontré cela après avoir appelé UIImagePickerController presentViewController: du rappel à un délégué UIAlertView. J'ai résolu le problème en poussant le presentViewController: appelez la trace d'exécution actuelle en utilisant 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
la source
C'est ce qui l'a résolu pour moi. J'essayais de présenter le UIImagePickerController depuis l'intérieur d'un bloc d'action d'UIAlertAction.
josefdlange
l'alerteView est obsolète, est-ce que cela fonctionnerait si j'utilisais l'async dans une action UIAlertViewController à la place?
DrPatience
@DrPatience Sure. dispatch_async fonctionne où vous voulez. Je ne sais pas si c'est nécessaire (cela dépendrait de votre code). Renseignez-vous sur GCD - il a de nombreuses utilisations.
Greg
12

J'ai eu ce problème lors de l'animation de certaines vues et l'application passait en mode arrière-plan et revenait. Je l'ai géré en définissant un indicateur isActive. Je l'ai réglé sur NON dans

- (void)applicationWillResignActive:(UIApplication *)application

et OUI dans

- (void)applicationDidBecomeActive:(UIApplication *)application

et animer ou non mes vues en conséquence. A pris soin de la question.

byedissident
la source
11

J'ai eu cela avec une feuille UIAlertControllerStyleActionSheet donnant à l'utilisateur la possibilité de prendre une photo avec l'appareil photo ou d'en utiliser une de la bibliothèque.

J'ai essayé un point d'arrêt symbolique sur le message d'erreur entrez la description de l'image ici

Cela m'a montré que l'erreur est produite par l'utilisation interne d'un UICollectionView lors de la présentation

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

entrez la description de l'image ici

J'ai corrigé cela en définissant explicitement le cadre avant de présenter

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

Voici la méthode complète qui fonctionne sans l'erreur

-(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:^(){
}];}
Yedy
la source
10

Vous pouvez désactiver l'avertissement "Instantané d'une vue" en référençant la viewpropriété avant de présenter le contrôleur de vue. Cela entraîne le chargement de la vue et permet à iOS de la rendre avant de prendre l'instantané.

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
la source
C'est une astuce presque incroyablement utile. Je vous remercie!!!! (Dans mon cas, je reçois toujours l'avertissement, mais l'application ne se bloque plus.)
Fattie
Cependant, lorsque j'ajoute un cameraOverlayView , malheureusement, je reçois toujours ce problème même lorsque j'applique ce conseil.
Fattie
8

Pour toute personne qui voit un problème avec un aperçu noir après la capture d'image, masquer la barre d'état après que l'UIPickerController est affiché semble résoudre le problème.

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
la source
1
J'ai sauvé ma journée! J'ai essayé les méthodes ci-dessus, aucune n'a fonctionné
Stan
La solution ne fonctionne pas. Je pense que lorsque nous capturons une image à ce moment-là, StatusBar est déjà masqué.
Mihir Oza
5

J'ai trouvé le même problème et j'ai tout essayé. J'ai deux applications différentes, une en objectif C et une en rapide - les deux ont le même problème. Le message d'erreur apparaît dans le débogueur et l'écran devient noir après la première photo. Cela ne se produit que dans iOS> = 8.0, c'est évidemment un bug.

J'ai trouvé une solution de contournement difficile. Fermez les commandes de la caméra avec imagePicker.showsCameraControls = false et créez votre propre overlayView qui a les boutons manquants. Il existe différents didacticiels sur la façon de procéder. Le message d'erreur étrange reste, mais au moins l'écran ne devient pas noir et vous avez une application qui fonctionne.

Thomas Zimmer
la source
J'ai eu exactement le même problème que vous, voir ma réponse ci-dessous.
Dan
5

Cela pourrait être un bogue de ImagePickerController intégré. Mon code fonctionne, mais se bloque parfois sur iPhone 6 Plus.

J'ai essayé toutes les solutions suggérées par d'autres réponses mais il n'y a pas eu de chance. Problème finalement résolu après le passage à JPSImagePickerController .

JonSlowCN
la source
3

J'ai tout essayé, mon problème était que le sélecteur d'images pour l'appareil photo et la photothèque a disparu juste après leur affichage. Je l'ai résolu avec la ligne suivante (rapide)

imagePicker.modalPresentationStyle = UIModalPresentationStyle.OverCurrentContext
Waffeln
la source
3

Je suis presque sûr que ce n'est qu'un bug dans iOS 8.0. Il est reproductible avec la plus simple des applications POC qui ne fait rien de plus que de présenter un UIImagePickerController comme vous le faites ci-dessus. De plus, il n'y a pas de modèle alternatif à l'affichage du sélecteur d'image / caméra, à ma connaissance. Vous pouvez même télécharger l'exemple d'application Apple utilisant UIImagePickerController, l'exécuter et cela générera la même erreur hors de la boîte.

Cela dit, la fonctionnalité fonctionne toujours pour moi. Outre l'avertissement / l'erreur, avez-vous des problèmes avec le fonctionnement de votre application?

Gaurav Patel
la source
3

Si nous utilisons le UIImagePickerController tant que propriété, cet avertissement disparaîtra.supposons que nous n'utilisons pas le résultat de la UIImagePickerController, si nous instancions l' UIImagePickerControllerintérieur d'une fonction.

Antony Ouseph
la source
2

Appeler cette méthode a fonctionné pour moi. Placez-le après avoir présenté votre vue.

[yourViewBeingPresented.view layoutIfNeeded];
Policier
la source
1

Je rencontre également le même problème et je l'ai résolu en vérifiant si la caméra est disponible:

BOOL cameraAvailableFlag = [UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera];
    if (cameraAvailableFlag)
        [self performSelector:@selector(showcamera) withObject:nil afterDelay:0.3];
aftab muhammed khan
la source
1
isSourceTypeAvailable renvoie true même si j'ai refusé l'accès à la caméra pour mon application. L'affichage est vide si l'accès à la caméra est refusé.
Καrτhικ
1

J'ai rencontré ce problème. Lorsque nous appelons la caméra et libérons les vues, ce problème est produit. Pour un exemple, appelez une caméra et définissez view nil dans la méthode viewDidDisappear, cette erreur se produira car il n'y a pas de rappel pour l'événement de caméra. Assurez-vous également de ce cas pour cette erreur.

Gobi M
la source
1

J'ai eu le même bug, obtenant un message ci-dessous dans la console lors de l'ouverture de la caméra.

«La capture instantanée d'une vue qui n'a pas été rendue entraîne une capture instantanée vide. Assurez-vous que votre vue a été rendue au moins une fois avant l'instantané ou l'instantané après les mises à jour de l'écran. '

Pour moi, le problème était avec le nom d'affichage Bundle dans Info.plist file.it était vide, j'ai mis le nom de mon application là et maintenant ça fonctionnait bien.Je n'ai reçu aucune alerte d'autorisation de caméra en raison du nom d'affichage Bundle vide.it bloqué le rendu de la vue.

le problème n'était pas visible, mais en le présentant sans autorisation.vous pouvez le vérifier dans les paramètres -> confidentialité -> Appareil photo, si votre application n'y figure pas, le problème pourrait être le même.

Shabeer Ali
la source
1

J'utilise Phonegap, mais ce fil continue à apparaître comme le premier lorsque Google recherche le message d'erreur.

Pour moi, ce problème a disparu en définissant le type d'image en PNG.

encodingType : Camera.EncodingType.PNG

Donc, toute la ligne étant:

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

Votre kilométrage peut varier, mais cela a fait l'affaire pour moi.

Jannunen
la source
1

Vous pouvez également envisager d'utiliser drawViewHierarchyInRect :

Rapide:

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

Objectif c:

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

    return image;
}

Regarde aussi:

Eric
la source
0

Dans mon cas (XCode 7 et iOS 9), j'utilise UINavigationController"caché", donc je dois ajouter UINavigationControllerDelegateau présent appareil photo ou rouler et ça fonctionne comme il est censé le faire! And pickerControllerDelegate.selfn'affiche pas non plus d'erreur!

Daniel Arantes Loverde
la source