wake-up-neo.com

iOS 8 Snapshots für eine Ansicht, die nicht gerendert wurde, führt zu einem leeren Snapshot

In iOS 8 habe ich Probleme, Bilder von der Kamera zu erfassen 

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

Aber in iOS 8 bekomme ich Folgendes:

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.

Ich habe es mit der Lösung von This Post mit probiert 

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

und das

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

und das

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

und das

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

und das

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

}];

irgendeine Idee?

228
souvickcse

Ich bin mir ziemlich sicher, dass dies nur ein Fehler in iOS 8.0 ist. Es ist reproduzierbar mit den einfachsten POC-Apps, die nichts weiter tun, als eine UIImagePickerController wie oben darzustellen. Außerdem gibt es meines Wissens kein alternatives Muster zur Anzeige des Bildaufnehmers/der Kamera. Sie können sogar die/App Apples Using UIImagePickerController herunterladen, ausführen, und es wird derselbe Fehler sofort erzeugt.

Allerdings funktioniert die Funktionalität für mich immer noch. Haben Sie neben der Warnung/dem Fehler Probleme mit der Funktion Ihrer App?

131
KevinH

Ich hatte mehrere Stunden mit diesem Problem zu kämpfen, ich habe jedes relevante Thema gelesen und festgestellt, dass der Fehler verursacht wurde, weil unter den Datenschutzeinstellungen meines Geräts der Zugriff der Kamera auf meine App blockiert wurde !!! Ich habe nie den Zugriff auf die Kamera verweigert und ich weiß nicht, wie die Kamera blockiert wurde, aber das war das Problem!

45
Pantelis Proios

Ich habe nicht genügend Reputationspunkte, um die Antwort von @ greg oben zu kommentieren. Ich werde meine Beobachtungen hier hinzufügen. Ich habe ein Swift-Projekt für iPad und iPhone. Ich habe eine Methode in meinem Main View Controller (relevantes Bit weiter unten). Wenn ich dies an einem Telefon teste, funktioniert alles einwandfrei und es werden keine Warnungen generiert. Wenn ich es auf einem iPad starte, funktioniert alles einwandfrei, aber ich sehe die Warnung vor dem Snapshot der Ansicht. Das Interessante ist jedoch, dass alles, wenn ich auf einem iPad ohne den Popover-Controller laufe, ohne Warnung ordnungsgemäß funktioniert. Leider verlangt Apple, dass der Bildwähler innerhalb eines Popovers auf dem iPad verwendet werden muss, wenn die Kamera nicht verwendet wird.

    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

Ich bin darauf gestoßen, nachdem ich UIImagePickerController presentViewController aufgerufen hatte: vom Callback zu einem UIAlertView-Delegierten. Ich habe das Problem gelöst, indem ich den presentViewController gedrückt habe: Abrufen der aktuellen Ablaufverfolgung mithilfe von 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

Ich hatte dieses Problem, als ich einige Ansichten animierte, und die App würde in den Hintergrundmodus wechseln und zurückkehren. Ich habe es durch das Setzen eines Flags isActive gehandhabt. Ich habe es auf NEIN gesetzt

- (void)applicationWillResignActive:(UIApplication *)application

und JA in

- (void)applicationDidBecomeActive:(UIApplication *)application

und meine Ansichten entsprechend animieren oder nicht. Kümmerte sich um das Problem.

12
byedissident

Ich hatte dies mit einem UIAlertControllerStyleActionSheet, das dem Benutzer die Möglichkeit gab, ein Foto mit der Kamera zu machen oder eines aus der Bibliothek zu verwenden.

Ich habe einen symbolischen Haltepunkt in der Fehlermeldung ausprobiert  enter image description here

Dies zeigte, dass der Fehler durch die interne Verwendung einer UICollectionView während der Präsentation erzeugt wurde

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

 enter image description here

Ich habe dieses Problem behoben, indem ich den Rahmen vor dem Präsentieren explizit eingestellt habe

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

Hier ist die vollständige Methode, die ohne Fehler funktioniert

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

Sie können die Warnung "Momentaufnahme einer Ansicht" stummschalten, indem Sie auf die view -Eigenschaft verweisen, bevor Sie den Ansichts-Controller anzeigen. Dadurch wird die Ansicht geladen und iOS kann vor dem Erstellen des Schnappschusses gerendert werden.

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

Für jeden, der nach der Bilderfassung ein Problem mit einer schwarzen Vorschau sieht, scheint das Ausblenden der Statusleiste nach dem Anzeigen des UIPickerControllers das Problem zu beheben.

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

Ich fand das gleiche Problem und versuchte alles. Ich habe zwei verschiedene Apps, eine in Objective-C und eine in Swift - beide haben das gleiche Problem. Die Fehlermeldung erscheint im Debugger und der Bildschirm wird nach dem ersten Foto schwarz. Dies ist nur bei iOS> = 8.0 der Fall, offensichtlich ist es ein Fehler.

Ich habe eine schwierige Lösung gefunden. Schließen Sie die Kamerasteuerung mit imagePicker.showsCameraControls = false und erstellen Sie ein eigenes OverlayView, das die fehlenden Schaltflächen enthält. Es gibt verschiedene Tutorials rund um das Vorgehen. Die seltsame Fehlermeldung bleibt erhalten, aber zumindest wird der Bildschirm nicht schwarz und Sie haben eine funktionierende App.

5
Thomas Zimmer

Dies kann ein Fehler des eingebauten ImagePickerControllers sein. Mein Code funktioniert, stürzt jedoch gelegentlich auf dem iPhone 6 Plus ab.

Ich habe alle Lösungsansätze aus anderen Antworten ausprobiert, aber es gab kein Glück. Problem endgültig behoben, nachdem auf JPSImagePickerController gewechselt wurde.

5
JonSlowCN

Wenn wir die UIImagePickerController als Eigenschaft verwenden, verschwindet diese Warnung. xcode gehe davon aus, dass wir das Ergebnis der UIImagePickerController nicht verwenden, wenn die UIImagePickerController innerhalb einer Funktion instanziiert wird.

3
Antony Ouseph

Ich bin mir ziemlich sicher, dass dies nur ein Fehler in iOS 8.0 ist. Es ist reproduzierbar mit den einfachsten POC-Apps, die nichts weiter tun, als einen UIImagePickerController wie oben beschrieben zu präsentieren. Außerdem gibt es meines Wissens kein alternatives Muster zur Anzeige des Bildaufnehmers/der Kamera. Sie können sogar die Beispiel-App "UIImagePickerController" von Apple herunterladen, ausführen und es wird derselbe Fehler sofort generiert.

Allerdings funktioniert die Funktionalität für mich immer noch. Haben Sie neben der Warnung/dem Fehler Probleme mit der Funktion Ihrer App?

3
Gaurav Patel

Ich habe alles versucht, mein Problem war, dass der Bild-Picker für die Kamera und die Fotobibliothek direkt nach dem Zeigen verschwunden ist. Ich habe es mit der folgenden Zeile gelöst (Swift)

imagePicker.modalPresentationStyle = UIModalPresentationStyle.OverCurrentContext
3
Waffeln

Der Aufruf dieser Methode hat für mich funktioniert. Platzieren Sie es, nachdem Sie Ihre Ansicht präsentiert haben.

[yourViewBeingPresented.view layoutIfNeeded];
2
Bobby

Ich habe den gleichen Fehler bekommen, als ich die Kamera öffnete. 

'Das Snapshot einer Ansicht, die nicht gerendert wurde, führt zu einem leeren Snapshot. Stellen Sie sicher, dass Ihre Ansicht mindestens einmal gerendert wurde, bevor Sie nach Bildschirmaktualisierungen Snapshots oder Snapshots erstellen. '

Für mich war das Problem mit dem Anzeigenamen des Pakets in der Datei "Info.plist". Es war leer, wie, ich habe meinen App-Namen dort eingetragen und nun funktioniert es gut Die Ansicht wurde für das Rendern blockiert. 

das Problem war nicht bei der Ansicht, sondern bei der Anzeige ohne Erlaubnis. Sie können die Einstellungen unter Einstellungen -> Datenschutz -> Kamera überprüfen. 

1
Shabeer Ali

Ich bin auf dieses Problem gestoßen. Wenn wir die Kamera anrufen und die Ansichten freigeben, entsteht dieses Problem. In einem Beispiel rufen Sie eine Kamera auf, und setzen Sie in der Methode viewDidDisappear keine Ansicht. Dieser Fehler tritt auf, da kein Rückruf für das Kameraereignis vorliegt. Vergewissern Sie sich auch für diesen Fall für diesen Fehler.

1
Gobi M

Ich verwende Phonegap, aber dieser Thread wird immer als erster angezeigt, wenn Sie über die Fehlermeldung googeln.

Für mich ist dieses Problem durch die Definition des Imagetyps für PNG verschwunden.

encodingType : Camera.EncodingType.PNG

Die ganze Linie ist also:

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

Ihre Laufleistung kann unterschiedlich sein, aber das hat mir geholfen.

1
Jannunen

Alternativ können Sie auch drawViewHierarchyInRect verwenden:

Swift:

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

Ziel c:

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

    return image;
}

Siehe auch:

1
Eric

Ich stelle auch das gleiche Problem fest und löste es, indem ich überprüfe, ob die Kamera verfügbar ist:

BOOL cameraAvailableFlag = [UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera];
    if (cameraAvailableFlag)
        [self performSelector:@selector(showcamera) withObject:nil afterDelay:0.3];
1

In meinem Fall (XCode 7 und iOS 9) verwende ich UINavigationController "hidden", also muss ich UINavigationControllerDelegate zur Präsentation der Kamera oder des Rollens hinzufügen, und es funktioniert wie erwartet! And pickerControllerDelegate.self zeigt auch keinen Fehler an!