iOS 8快照未呈现的视图会导致快照为空


228

在iOS 8中,我无法从相机捕获图像,直到现在为止,我一直将此代码用于

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

但是在iOS 8中,我得到了这个:

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.

我曾尝试与所提供的解决方案这个帖子

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

还有这个

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

还有这个

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

还有这个

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

还有这个

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

}];

任何想法?


3
遇到同样的问题,而且这个错误使我的应用有时崩溃。希望更新8.0.2将解决此错误。当我在iOS7中运行我的应用程序时,它的工作原理就像魅力,没有任何愚蠢的警告。看起来iOS 8可以长期稳定。
NCFUSN

9
使用8.0.2更新的事件此问题仍然存在
ArdenDev 2014年

2
我遇到了同样的问题。拍照后,我正在另一个线程中进行一些处理。将代码移至主线程后,一切正常。即,我之前的代码是:dispatch_async(dispatch_get_main_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{我更改为dispatch_async(dispatch_get_main_queue(), ^{
mikeyq6,2014年

9
同样的问题发生在iOS 8.1
Raptor 2014年

12
在iOS 9中也会发生。
Sebyddd

Answers:


131

我很确定这只是iOS 8.0中的错误。它可以通过最简单的POC应用程序重现,该应用程序无非UIImagePickerController就是尝试呈现您在上面所做的那样。此外,据我所知,除了显示图像选择器/相机外,没有其他模式。您甚至可以下载Apple的Using UIImagePickerController示例应用程序,运行它,它会立即产生相同的错误。

也就是说,该功能仍然适用于我。除了警告/错误之外,您的应用程序功能是否还有问题?


2
是的,这可能是一个错误,代码对我来说也很好。
souvickcse 2014-09-24

4
@souvickcse我也遇到此错误。每当发生新照片时,弹出的图像预览都是全黑的。但是,屏幕底部的“重新拍摄”和“使用照片”按钮仍会出现并正常工作。您是否在目睹同样的行为?
巴里·比尔曼

3
@souvickcse我正在使用位于此处的最新phonegap相机插件基准:github.com/apache/cordova-plugin-camera。一切工作与iOS 7.1运行良好,在iPhone 5,但我无法找到一个方法来得到它正常工作在iPhone 6使用的是iOS 8
巴里Beerman

2
iOS8.1决赛对我来说也一样
fvisticot

4
仍然存在于IOS 9中
牧师

45

我在这个问题上苦苦挣扎了几个小时,我已经阅读了所有相关主题,并发现该错误是由于在我的设备的隐私设置下,相机对我的应用程序的访问被阻止而造成的!!!我从未拒绝使用相机,也不知道它是如何被阻止的,但这就是问题所在!


4
我不确定它是否真的对您有用,但对我却不起作用。我只是希望@KevinH是正确的。
Deepak Thakur 2014年

4
不,在我的情况下,该应用程序的摄像头访问权限已选中。但是我确实相信这可能是由设置间接引起的:对设置的更改有时不会立即生效,cupertino中的某个人必须优化了一个呼叫以使其与某处同步
Anton Tropashko 2015年

这个建议为我解决了这个问题。当我的应用程序中出现相机选择器时,我之前曾触摸过“不允许”。我以为每次访问相机都会问我,但事实并非如此。我必须转到“设置”>“隐私”>“相机”,然后打开应用程序的滑块。然后它正常工作。似乎每次都不要问苹果这有点愚蠢……
John Contarino 2015年

确切地说,有时我们不认为这种类型的错误会引起问题。thx伙伴非常有帮助
Javed Multani先生

最好的选择是在使用相机检测该功能是否处于活动状态之前,否则,请警告用户在设置上激活相机之前无法拍照。在iOS 10上,可以将用户转到特定的应用程序设置(在iOS 8之前是可能的,但是如果我没记错的话,在iOS 8和9中是不可能的)。
kindaian

33

我的信誉点不足,无法评论上面的@greg答案,因此将在此处添加我的观察结果。我有一个iPad和iPhone的Swift项目。我的主视图控制器内部有一个方法(下面是相关位)。当我在电话上对此进行测试时,一切正常,并且不会生成警告。当我在iPad上运行它时,一切正常,但是我看到有关快照视图的警告。但是,有趣的一点是,当我在iPad上运行而未使用弹出框控制器时,一切正常,没有任何警告。不幸的是,Apple要求如果不使用相机,则必须在iPad的弹出框内使用图像选择器。

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

看起来这是一个正确的建议,因为即使在iOS 9.0.2中,我也会收到该错误消息。我只有iPhone应用程序,当我在iPad Mini上运行它时,在显示图像选择器时会看到该消息。由于某种原因,iOS认为我运行iPad应用程序。
约翰·特雷西

16

在从回调到UIAlertView委托调用UIImagePickerController presentViewController:之后,我遇到了这个问题。我通过推送presentViewController解决了该问题:使用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];
    });
}

这就是为我解决的问题。我试图从UIAlertAction的操作块内部呈现UIImagePickerController。
josefdlange 2015年

alertView已被弃用,如果我改为在UIAlertViewController动作中使用async,则可以正常工作吗?
DrPatience

@DrPatience当然。dispatch_async可以在任何您需要的地方工作。我不知道这是必要的(将取决于您的代码)。在GCD上阅读-它有很多用途。
greg 2015年

12

给某些视图设置动画时,我遇到了这个问题,该应用程序将进入后台模式并返回。我通过设置标志isActive来处理它。我将其设置为否

- (void)applicationWillResignActive:(UIApplication *)application

和是

- (void)applicationDidBecomeActive:(UIApplication *)application

并相应地使我的观点动起来。照顾了这个问题。


11

我通过UIAlertControllerStyleActionSheet来实现这一点,它为用户提供了使用相机拍摄照片或使用图库中的照片的选项。

我在错误消息上尝试了一个符号断点 在此处输入图片说明

这告诉我错误是由于在演示过程中对UICollectionView的内部使用而产生的

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

在此处输入图片说明

我通过在展示之前明确设置框架来解决此问题

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

这是没有错误的完整方法

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

10

您可以view在呈现视图控制器之前通过引用属性来使“快照视图快照”警告静音。这样做会导致视图加载,并允许iOS在拍摄快照之前对其进行渲染。

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

这几乎是一个有用的技巧。谢谢!!!!(就我而言,我仍然收到警告,但该应用不再崩溃。)
Fattie

但是,当我添加时cameraOverlayView,不幸的是,即使应用此技巧,我仍然会遇到此问题。
Fattie

8

对于任何在图像捕获后看到黑色预览问题的人,在显示UIPickerController之后隐藏状态栏似乎可以解决问题。

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

1
!完全救了我的一天,我都试过以上方法,没有worked.and这个工作
斯坦

解决方案不起作用。我认为当我们当时捕获图像时,StatusBar已经隐藏。
Mihir Oza

5

我发现了同样的问题,并尝试了一切。我有两种不同的应用程序,一种在Objective-C中,另一种在Swift中-都有相同的问题。错误消息出现在调试器中,并且在第一张照片后屏幕变黑。这仅在iOS> = 8.0中发生,显然是一个错误。

我发现了一个困难的解决方法。使用imagePicker.showsCameraControls = false关闭相机控件,并创建具有缺少按钮的自己的overlayView。有关如何执行此操作的各种教程。奇怪的错误消息仍然存在,但至少屏幕没有变黑,并且您的应用程序正常工作。


我遇到了与您完全相同的问题,请参见下面的答案。
2015年

5

这可能是内置ImagePickerController的错误。我的代码正常工作,但偶尔在iPhone 6 Plus上崩溃。

我已经尝试了其他答案建议的所有解决方案,但是没有运气。切换到JPSImagePickerController之后,问题终于解决了。


3

我已经尝试了所有方法,但问题是相机和照片库的图像选择器在显示后就消失了。我用以下几行(快速)解决了它

imagePicker.modalPresentationStyle = UIModalPresentationStyle.OverCurrentContext

3

我很确定这只是iOS 8.0中的错误。它可以用最简单的POC应用程序重现,该应用程序仅像您在上面所做的那样尝试呈现UIImagePickerController。此外,据我所知,除了显示图像选择器/相机外,没有其他模式。您甚至可以下载Apple的Using UIImagePickerController示例应用程序,运行它,它会立即产生相同的错误。

也就是说,该功能仍然适用于我。除了警告/错误之外,您的应用程序功能是否还有问题?



2

调用此方法对我有用。提出您的看法后将其放置。

[yourViewBeingPresented.view layoutIfNeeded];

1

我也遇到了同样的问题,并通过检查相机是否可用来解决了这个问题:

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

1
即使我拒绝访问我的应用程序的相机,isSourceTypeAvailable也会返回true。如果拒绝摄像机访问,则显示为空白。
Καrτhικ

1

我遇到了这个问题。当我们调用相机并释放视图时,就会产生此问题。例如,调用一个照相机并在viewDidDisappear方法中设置view nil会出现此错误,因为没有照相机事件的回调。对于此错误,也请确保这种情况。


1

我遇到了同样的错误,在打开相机时在控制台中得到了下面的消息。

'快照未渲染的视图将导致快照为空。确保在快照之前或屏幕更新之后至少快照已经渲染过一次视图。”

对我来说,问题是Info.plist文件中的Bundle显示名称。它在某种程度上是空的,我把我的应用程序名称放在那里,现在它可以正常工作。由于Bundle显示名称为空,我没有收到任何相机权限警报。阻止了视图的渲染。

问题不在于视图,而是未经许可提出。您可以在设置->隐私->相机上进行检查,如果未列出您的应用,则问题可能是相同的。


1

我正在使用Phonegap,但是在Google搜索错误消息时,该线程一直作为第一个线程出现。

对我来说,这个问题通过将图像类型定义为PNG而消失了。

encodingType : Camera.EncodingType.PNG

所以整行是:

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

您的里程可能会有所不同,但这对我有用。


1

或者,考虑使用drawViewHierarchyInRect

迅速:

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

目标C:

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

    return image;
}

另请参阅:


By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.