15

I'm getting hundreds of crashes from one of my live apps ever since people started upgrading to iOS 7. Has anyone else seen this problem? Nothing reproduces on my iPad 3 with iOS 7...

Link to 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
jjxtra
  • 20,415
  • 16
  • 100
  • 140
  • when you say "nothing reproduces", what about your `Fatal Exception CALayerInvalidGeometry`? does the app procede to function fine after that? try fixing that issue and see what happens. – ljs.dev Sep 22 '13 at 03:07
  • 2
    We can't get the exception to happen in our testing. We only know about it from Crashlytics and assume it crashes out of the app. – jjxtra Sep 22 '13 at 03:51
  • 2
    I am getting the same thing - let's compare notes. I assume this starts with the UIImagePickerController. I am using it for both camera and photo library access. I suspect this is crashing during photo library access due to the navigationbar stuff. I put the image picker in a UIPopoverController and present that to the user - maybe that has something to do with it? – kurtzmarc Sep 25 '13 at 02:24
  • 2
    I get the same thing in this scenario only: first time I bring up library version of picker from a uibarbuttonitem on iPad. System ask user to grant permission to access photo lib. User says yes and I get above crash. – Morgan Sep 25 '13 at 03:59
  • Thank you @Morgan! I can now reproduce the problem! Not sure what the solution is yet, but that certainly triggers the crash. – kurtzmarc Sep 25 '13 at 15:09
  • 1
    I am getting this problem when showing UIImagePickerController on iPad on iOS 7 from a UIBarButtonItem accessing the photo library. Anyone know how to reset the photo privacy so that is shows the photo privacy message again? – jjxtra Sep 25 '13 at 15:49
  • Found this from another stackoverflow question: On the device you can reset the privacy settings in the "Settings" app (General > Reset > Reset Location & Privacy). – jjxtra Sep 25 '13 at 15:55
  • @Morgan I don't get a crash in the scenario you describe – jjxtra Sep 25 '13 at 16:16
  • @Morgan after resetting location and privacy settings to factory default I now get the crash. – jjxtra Sep 25 '13 at 16:28
  • @kurtzmarc I'll let you know if I find a fix, will try and get it fixed tonight. – jjxtra Sep 25 '13 at 16:30
  • Just FYI all I submitted a bug report to Apple, the id is 15077496 – jjxtra Sep 25 '13 at 16:34
  • 1
    Suggested work-around would be to call an ALAssetLibrary call to get the thumbnail image or something which will work OR cause the dialog to show. Then in the block of the callback, show the image picker. – jjxtra Sep 25 '13 at 16:36

3 Answers3

16

Collectively we've come to the conclusion that this is a bug in iOS 7 on iPad. It occurs when you attempt to show a UIImagePickerController in a UIPopoverControl from a UIBarButtonItem for the first time. After the user grants permission to their photo album the crash happens. It appears the solution for now is to request permission to photos before opening the UIPopoverControl. Here is how I implemented my solution:

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

Don't forget to add AssetsLibrary.framework to your project.

kurtzmarc
  • 3,110
  • 1
  • 24
  • 40
  • Just FYI I filed a bug with Apple, id 15077496 – jjxtra Sep 26 '13 at 03:00
  • kurtzmarc thanks for posting this. I am very surprised this made it past Apple's QA... – jjxtra Sep 26 '13 at 03:36
  • I can't find that bug report on Apple's site. Is it marked private? – kurtzmarc Sep 28 '13 at 13:55
  • I can't see anywhere in the bug report to toggle public / private – jjxtra Sep 28 '13 at 15:30
  • nvm - you can't see other people's bug reports (hence the need for open radar). I had forgotten that. – kurtzmarc Oct 04 '13 at 03:21
  • I found to reproduce the crash, uninstalling the app or disabling photo access in privacy wasn't enough. Most reliable was to use the iOS Simulator's 'reset content & settings' option and the re-install and re-run the app. Then I could get the crash each time. Now I can try your fix... – Ben Clayton Feb 27 '14 at 15:02
  • Looks like it has been fixed in IOS 7.1 – kasuku Mar 14 '14 at 13:16
0

I was having the same issue.

I had a UIImagePickerController displayed inside a UIPopoverController with the size defined by UIImagePickerController's contentSizeForViewInPopover function.
To fix this issue I changed UIPopoverController size to UIImagePickerController's preferredContentSize function.

Rahul Patel
  • 5,858
  • 6
  • 46
  • 72
fnxpt
  • 434
  • 3
  • 13
0

You can use custom Frame and load the popover as below

[popOver presentPopoverFromRect:CGRectMake(self.view.frame.size.width-50, 50, 10, 10) inView:self.view permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
Rahul Patel
  • 5,858
  • 6
  • 46
  • 72
Yatin
  • 26
  • 6