UIImagePickerController 在iOS 7上仅在iPad设备上出现崩溃

15

自从人们开始升级到iOS 7以来,我的一个实时应用程序中出现了数百次崩溃。有其他人遇到过这个问题吗?在我的安装了iOS 7的iPad 3上无法重现任何问题...

Crashlytics链接:crashes.to/s/edf2e71d9a5

Fatal Exception CALayerInvalidGeometry
CALayer position contains NaN: [nan nan]
0 ...    CoreFoundation  __exceptionPreprocess + 130
2    CoreFoundation  -[NSException initWithCoder:]
3    QuartzCore      CA::Layer::set_position(CA::Vec2<double> const&, bool) + 242
4    QuartzCore  -[CALayer setPosition:] + 54
5    QuartzCore  -[CALayer setFrame:] + 594
6    UIKit   -[UIView(Geometry) setFrame:] + 254
7    UIKit   -[UILabel setFrame:] + 138
8    UIKit   -[UINavigationItemView initWithNavigationItem:] + 384
9    UIKit   -[UINavigationItem _titleView] + 92
10   UIKit   -[UINavigationBar _prepareForPushAnimationWithItems:] + 68
11   UIKit   -[UINavigationBar pushNavigationItem:] + 292
12   UIKit   -[UINavigationBar _pushNavigationItem:transition:] + 386
13   UIKit   __71-[UINavigationController pushViewController:transition:forceImmediate:]_block_invoke + 150
14   UIKit   -[UINavigationController pushViewController:transition:forceImmediate:] + 1384
15   UIKit   -[UINavigationController pushViewController:animated:] + 294
16   UIKit   -[UIImagePickerController _setupControllersForCurrentSourceType] + 112
17   UIKit   -[UIImagePickerController setSourceType:] + 456
18 ...   libdispatch.dylib   _dispatch_call_block_and_release + 10
19   libdispatch.dylib   _dispatch_client_callout + 22
20   libdispatch.dylib   _dispatch_main_queue_callback_4CF$VARIANT$mp + 268
21   CoreFoundation  __CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__ + 8
22   CoreFoundation  __CFRunLoopRun + 1300
23   CoreFoundation  CFRunLoopRunSpecific + 522
24   CoreFoundation  CFRunLoopRunInMode + 106
25   GraphicsServices    GSEventRunModal + 138
26   UIKit   UIApplicationMain + 1136

2
我们无法在测试中触发异常。我们只知道它来自Crashlytics,并且假定它会导致应用程序崩溃。 - jjxtra
2
我也遇到了同样的问题 - 我们来比较一下。我猜这是从UIImagePickerController开始的。我同时使用它来访问相机和照片库。我怀疑这在访问照片库时由于导航栏的问题而崩溃。我将图像选择器放在UIPopoverController中,并向用户呈现 - 也许这与此有关? - kurtzmarc
2
在这种情况下,我只会得到同样的东西:第一次从iPad上的uibarbuttonitem打开选择器库版本。系统要求用户授予访问照片库的权限。用户说“是”,然后我就遇到了上述崩溃。 - Morgan
1
当在iOS 7的iPad上从UIBarButtonItem访问照片库并展示UIImagePickerController时,我遇到了这个问题。有人知道如何重置照片隐私设置,以便再次显示照片隐私消息吗? - jjxtra
1
建议的解决方法是调用ALAssetLibrary来获取缩略图或其他可行的方法,以便触发对话框的显示。然后在回调块中显示图像选择器。 - jjxtra
显示剩余7条评论
3个回答

16

我们共同得出结论,这是iPad上iOS 7中的一个 bug。当您尝试从 UIBarButtonItem 首次显示 UIImagePickerController 在 UIPopoverControl 中时,就会发生崩溃。在用户授权其照片相册后,崩溃就会发生。目前的解决方案似乎是在打开 UIPopoverControl 之前先请求访问照片权限。以下是我实现解决方案的方法:

// Photo Library
if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypePhotoLibrary])
{
    void(^blk)() =  ^() {
        UIImagePickerController* picker = [[UIImagePickerController alloc] init];
        picker.delegate = self;
        picker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
        if (NIIsPad()) {
            UIPopoverController* popover = [[UIPopoverController alloc] initWithContentViewController:picker];
            [popover presentPopoverFromBarButtonItem:self.popoverAnchor permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
        } else {
            [self.navigationController presentModalViewController:picker animated:YES];
        }
    };

    // Make sure we have permission, otherwise request it first
    ALAssetsLibrary* assetsLibrary = [[ALAssetsLibrary alloc] init];
    ALAuthorizationStatus authStatus;
    if (IOS_VERSION_GREATER_THAN_OR_EQUAL_TO(@"6.0"))
        authStatus = [ALAssetsLibrary authorizationStatus];
    else
        authStatus = ALAuthorizationStatusAuthorized;

    if (authStatus == ALAuthorizationStatusAuthorized) {
        blk();
    } else if (authStatus == ALAuthorizationStatusDenied || authStatus == ALAuthorizationStatusRestricted) {
        [[UIAlertView alertViewWithTitle:@"Grant photos permission" message:@"Grant permission to your photos. Go to Settings App > Privacy > Photos."] show];
    } else if (authStatus == ALAuthorizationStatusNotDetermined) {
        [assetsLibrary enumerateGroupsWithTypes:ALAssetsGroupAll usingBlock:^(ALAssetsGroup *group, BOOL *stop) {
            // Catch the final iteration, ignore the rest
            if (group == nil)
                dispatch_async(dispatch_get_main_queue(), ^{
                    blk();
                });
            *stop = YES;
        } failureBlock:^(NSError *error) {
            // failure :(
            dispatch_async(dispatch_get_main_queue(), ^{
                [[UIAlertView alertViewWithTitle:@"Grant photos permission" message:@"Grant permission to your photos. Go to Settings App > Privacy > Photos."] show];
            });
        }];
    }
}

不要忘记将AssetsLibrary.framework添加到您的项目中。


只是提供信息,我向苹果提交了一个错误报告,编号为15077496。 - jjxtra
kurtzmarc感谢您发布这个问题。我非常惊讶这个问题通过了苹果的QA... - jjxtra
我在苹果的网站上找不到那个错误报告。它被标记为私有了吗? - kurtzmarc
我在错误报告中没有看到切换公共/私有的任何地方。 - jjxtra
我发现要重现崩溃,仅仅卸载应用程序或在隐私中禁用照片访问是不够的。最可靠的方法是使用iOS模拟器的“重置内容和设置”选项,然后重新安装和运行应用程序。这样,我每次都可以得到崩溃。现在我可以尝试您的修复方案... - Ben Clayton
显示剩余2条评论

0

您可以使用自定义框架并按如下方式加载弹出窗口

[popOver presentPopoverFromRect:CGRectMake(self.view.frame.size.width-50, 50, 10, 10) inView:self.view permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];

0

我遇到了同样的问题。

我在一个UIPopoverController中显示了一个UIImagePickerController,并使用UIImagePickerControllercontentSizeForViewInPopover函数定义了大小。
为了解决这个问题,我将UIPopoverController的大小改为UIImagePickerControllerpreferredContentSize函数。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接