Photos, please. Block-based permissions in iOS 7

I recently built an app that lets you turn one of your own photos into a nice wallpaper or background. You pick a photo from your Photos library and then apply blur and/or pixellation effects until you're satisfied.

Your app crashed when we tapped to import a photo.

The app was rejected during review yesterday for crashing on both iPad and iPhone. I was surprised as my testing setup matches what the App Review team used during testing (iPad, iPhone 5s, iOS 7.0.4) I even tested with an ad hoc archived ipa to rule out compiler optimizations as the culprit.

The crash log showed some issues during the presentation of the UIImagePickerController.

[CALayer setPosition:] + 50
[CALayer setFrame:] + 590
[UIView(Geometry) setFrame:] + 250
[UILabel setFrame:] + 134
[UINavigationItemView initWithNavigationItem:] + 380
[UINavigationItem _titleView] + 88
[UINavigationBar _prepareForPushAnimationWithItems:] + 64
[UINavigationBar pushNavigationItem:] + 288
[UINavigationBar _pushNavigationItem:transition:] + 382
_71-[UINavigationController pushViewController:transition:forceImmediate:]_block_invoke + 146
[UINavigationController pushViewController:transition:forceImmediate:] + 1380
[UINavigationController pushViewController:animated:] + 290
[UIImagePickerController _setupControllersForCurrentSourceType] + 108
[UIImagePickerController setSourceType:] + 452

I was finally able to reproduce the issue on iPad by resetting the location and privacy settings on my devices. To do that, open the Settings app and look under General > Reset > Reset Location and Privacy.

The first time the app tries to access the Photos library, an alert view pops up requesting permission. The problem is that I have no control over that and my UIPopoverController presenting the UIImagePickerController is presented at the same time. This can cause an issue on iOS 7, apparently - the popover frame contained an value that was NaN.

I needed a way to ask for permission and then present the popover. This StackOverflow post led to a solution that depends on the AssetsLibrary framework, which worked well for me.

ALAssetsLibrary *assetLibrary = [[ALAssetsLibrary alloc] init];
[assetLibrary enumerateGroupsWithTypes:ALAssetsGroupLibrary usingBlock:^(ALAssetsGroup *group, BOOL *stop) {
    if (group == nil) {
        // Present UIImagePickerController
    }
    *stop = YES; // stop after first iteration no matter what ALAssetsGroupType is used
} failureBlock:^(NSError *error) {
    // Access denied; present UI to let user know they can adjust Privacy settings
}];