In iOS 8, Apple has "soft-deprecated" UIPopoverController, replacing it with UIPopoverPresentationController. Behind the scenes this means that sometimes a UIPopoverPresentationController is being used without the developer's explicit intent to do so.
Case in point the 1Password app extension. The following line of code leads to a crash on iPads running iOS 8:
- (void)findLoginForURLString:(NSString *)URLString forViewController:(UIViewController *)viewController sender:(id)sender completion:(void (^)(NSDictionary *loginDictionary, NSError *error))completion {
// ...
[viewController presentViewController:activityViewController animated:YES completion:nil];
}
With the following crash log:
*** Terminating app due to uncaught exception 'NSGenericException', reason: 'UIPopoverPresentationController (<_UIAlertControllerActionSheetRegularPresentationController: 0x13ed0d8f0>) should have a non-nil sourceView or barButtonItem set before the presentation occurs.'
What's happening is that UIKit is forcing the activity view controller to be presented in a popover, but it isn't setting a sourceView/sourceRect pair nor a barButtonItem, leading to the above crash. This is undocumented behavior but I've seen it in other apps and contexts.
Suggested workarounds (both assume getting a reference to the activity view controller's popover presentation controller and setting the required properties):
- Hacky Bullshit – Just use
viewController's view as the sourceView/sourceRect on iPad.
- Better – Provide an alternate public API for implementers to explicitly provide a sourceRect/sourceView pair or barButtonItem when calling the extension.