web-dev-qa-db-fra.com

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

Dans iOS 8, je n'arrive pas à capturer les images de l'appareil photo jusqu'à présent. J'utilise ce code pour 

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 with 

@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?

228
souvickcse

Je suis à peu près sûr que c'est juste un bug dans iOS 8.0. Il est reproductible avec la plus simple des applications POC qui ne fait que tenter de présenter une UIImagePickerController comme vous le faites ci-dessus. De plus, il n'y a pas d'autre motif que d'afficher le sélecteur d'images/l'appareil photo, à ma connaissance. Vous pouvez même télécharger le d'Apple en utilisant l'exemple d'application UIImagePickerController , exécutez-le et il générera la même erreur immédiatement.

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

131
KevinH

Je me débattais avec ce problème pendant plusieurs heures. J'ai lu tous les sujets pertinents et découvert que l'erreur était due au fait que, dans les paramètres de confidentialité de mon appareil, l'accès de l'appareil photo à 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!

45
Pantelis Proios

Je n'ai pas assez de points de réputation pour commenter la réponse de @ greg ci-dessus, j'ajouterai donc mes observations ici. J'ai un projet Swift pour iPad et iPhone. J'ai une méthode dans mon contrôleur de vue principale (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 prise de vue en instantané. Ce qui est intéressant, toutefois, 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'images 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);
        }
    });
33
dlw

Je me suis heurté à cela après avoir appelé UIImagePickerController presentViewController: du rappel à un délégué UIAlertView. J'ai résolu le problème en poussant la commande presentViewController: appelez la trace d'exécution en cours à l'aide de 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];
    });
}
16
greg

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 traité en définissant un indicateur isActive. Je l'ai mis à NO dans

- (void)applicationWillResignActive:(UIApplication *)application

et OUI à

- (void)applicationDidBecomeActive:(UIApplication *)application

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

12
byedissident

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

J'ai essayé un point d'arrêt symbolique sur le message d'erreur  enter image description here

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

 enter image description here

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

Vous pouvez désactiver l'avertissement "Instantané d'une vue" en référençant la propriété view avant de présenter le contrôleur de vue. Cela entraîne le chargement de la vue et permet à iOS de la rendre avant la prise de 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];
10
Steve Shepard

Pour tous ceux qui voient un problème avec un aperçu noir après la capture d'image, masquer la barre d'état après l'affichage de UIPickerController 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];
            }
        }];
8
Dan

J'ai trouvé le même problème et j'ai tout essayé. J'ai deux applications différentes, une dans Objective-C et une dans Swift - 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, il s'agit évidemment d'un bogue.

J'ai trouvé une solution de contournement difficile. Fermez les contrôles de la caméra avec imagePicker.showsCameraControls = false et créez votre propre superposition avec les boutons manquants. Il existe différents tutoriels sur la procédure à suivre. Le message d'erreur étrange reste, mais au moins, l'écran ne devient pas noir et vous avez une application qui fonctionne.

5
Thomas Zimmer

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

J'ai essayé toutes les solutions suggérées par d'autres réponses, mais sans succès. Problème finalement résolu après le passage à JPSImagePickerController .

5
JonSlowCN

Si nous utilisons la variable UIImagePickerController en tant que propriété, cet avertissement disparaîtra. xcode supposons que nous n'utilisons pas le résultat de la UIImagePickerController, si nous instancions la UIImagePickerController dans une fonction.

3
Antony Ouseph

Je suis à peu près sûr que c'est juste un bug dans iOS 8.0. Il est reproductible avec la plus simple des applications POC qui ne fait rien de plus que tenter de présenter un UIImagePickerController comme vous le faites ci-dessus. De plus, il n'y a pas d'autre motif que d'afficher le sélecteur d'images/l'appareil photo, à ma connaissance. Vous pouvez même télécharger l'exemple d'application Using UIImagePickerController d'Apple, l'exécuter, et il générera la même erreur immédiatement.

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

3
Gaurav Patel

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 projection. Je l'ai résolu avec la ligne suivante (Swift)

imagePicker.modalPresentationStyle = UIModalPresentationStyle.OverCurrentContext
3
Waffeln

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

[yourViewBeingPresented.view layoutIfNeeded];
2
Bobby

J'ai eu le même bug, recevant 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 donne un instantané vide. Assurez-vous que votre vue a été rendue au moins une fois avant la prise de vue ou après la mise à jour de l'écran. '

Pour moi, le problème était lié au nom d'affichage de l'ensemble dans Info.plist. Fichier.it était vide. Comment, j'ai mis le nom de mon application ici et cela fonctionne correctement. bloqué la vue du rendu. 

le problème n'était pas avec la vue mais en le présentant sans autorisation. Vous pouvez le vérifier dans les paramètres -> confidentialité -> Appareil photo. 

1
Shabeer Ali

J'ai rencontré ce problème. Lorsque nous appelons la caméra et que nous relâchons les vues, ce problème est survenu. Pour un exemple, appelez une caméra et définissez view nil dans la méthode viewDidDisappear, cette erreur surviendra car il n'y a pas de rappel pour l'événement camera. Assurez-vous de ce cas aussi pour cette erreur.

1
Gobi M

J'utilise Phonegap, mais ce fil de discussion 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.

1
Jannunen

Sinon, envisagez 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:

1
Eric

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

Dans mon cas (XCode 7 et iOS 9), j’utilise UINavigationController "caché", je dois donc ajouter UINavigationControllerDelegate pour présenter l’appareil photo ou le rouleau et cela fonctionne comme prévu! And pickerControllerDelegate.self n'affiche pas d'erreur non plus!

0