Search code examples
iosipadios7storyboardsegue

iOS 7 Popover Controller crashing under xcode 6


Whenever I try to use a UIPopoverController on iOS7 my app crashes. As far as I know, this is a recent issue and only occurs when built in Xcode 6. I don't have an iOS 7 iPad for testing but I have received info from Crashlytics that someone is experiencing this crash. It also crashes in the 7.1 simulator.

Any help, greatly appreciated.

Cheers

My code that crashes, within prepareForSegue::

if ([[segue identifier] isEqualToString:iPadiOS7ColorPickerSegue])
{
    FCColorPickerViewController *colorPickerVC = [segue destinationViewController];
    colorPickerVC.delegate = self;
    colorPickerVC.isPopover = YES;
    self.popVC = [(UIStoryboardPopoverSegue *)segue popoverController]; // <-- This line
}

The error, note the UIStoryboardPushSegue even though it is set as a Popover in the storyboard.

*** Terminating app due to uncaught exception 'NSInvalidArgumentException', 
reason: '-[UIStoryboardPushSegue popoverController]: unrecognized selector sent to instance 0x7a1dd9a0'

Storyboard segue properties

EDIT

I have the view controllers set up in a unified storyboard. This code was working, however after my latest update using Xcode 6 I started receiving crash reports for this error.

It appears that my segue selection is not being respected as it seems to call UIStoryBoardPushSegue.


Solution

  • Instead of calling a segue, I ended up assigning the laid out view controller I was trying to present as a popover, a Storyboard Identifier. I could then use this as the contentViewController for a popoverController. (I would not have access to [segue destinationViewController], as I am no longer displaying it as a segue)

    The Push segue on iPhone, iOS7 seems unaffected so I have left it unchanged.

    I had to make the (UIPopoverController*) popVC property strong so as it retains a reference, then I free it when it is dismissed.

    Below is the code I use to check for iOS version and device and where the segues where called from.

    if ([NSProcessInfo instancesRespondToSelector:@selector(isOperatingSystemAtLeastVersion:)]) {
        // conditionally check for any version >= iOS 8 using 'isOperatingSystemAtLeastVersion'
        if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad) {
            [self performSegueWithIdentifier:kiPadiOS8ColorPickerSegueID sender:nil];
        } else {
            [self performSegueWithIdentifier:kiPhoneiOS8ColorPickerSegueID sender:nil];
        }
    } else {
        // we're on iOS 7 or below
        if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad) {
            //[self performSegueWithIdentifier:kiPadiOS7ColorPickerSegueID sender:nil];
    
            FCColorPickerViewController *colorPickerVC = [[UIStoryboard storyboardWithName:@"Main" bundle:nil]instantiateViewControllerWithIdentifier:@"ColorPickerPopover"];// = [ destinationViewController];
            colorPickerVC.delegate = self;
            colorPickerVC.isPopover = YES;
    
            self.popVC = [[UIPopoverController alloc] initWithContentViewController:colorPickerVC];
            [self.popVC presentPopoverFromRect:CGRectMake(0, CGRectGetHeight(self.view.frame) - 50, CGRectGetWidth(self.view.frame), 50) inView:self.view permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
    
        } else { // iPhone, iOS 7
            [self performSegueWithIdentifier:kiPhoneiOS7ColorPickerSegueID sender:nil];
        }
    
    }