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