I've researched just about every post I can find on this and have reached the point where I could use some help.
My project is a universal app built using storyboards. the iPad version uses a split view controller. Master view relatioship is a navigation controller with a view controller. Detail view is a navigation controller with a view controller.
Without realizing it I built and tested the app using iPad 5.1 simulator. Upon realizing that small detail and needing iOS 5.0 compatibility, I started testing in ios 5.0.
two big changes occurred: a) the split view shows in a popover, rather then full screen like in 5.1.1 (I prefer the popover actually) and b) my code to programmatically hide and show the popover/splitscreen which worked flawlessly in 5.1 does not work in 5.0 - the "show" actually crashes the app. I built a couple of methods to show/hide the popover to complement the UI and not just rely on orientation changes. For instance, I used the show method to put the popover on the screen in portrait but remove it after selection of a tableview, etc.
So, maybe someone can help. Here are the details and the questions - thanks so much in advance for your kind help:
iOS 5.1 - show pop up - I use the splitview controller delegate call to grab a reference to the popover button, then use the button action to show the popover from a method. This works perfect in 5.1 but caused this error in 5.0: ERROR: Popovers cannot be presented from a view which does not have a window.' (I've searched on this error and there are many references but not a specific answer for my configuration). Plus why is there a window available in 5.1 and not 5.0?
//show master view popover
[self.masterPopoverController presentPopoverFromBarButtonItem:self.showMasterViewButton permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
//get the reference from the button
- (void)splitViewController:(UISplitViewController *)splitController willHideViewController:(UIViewController *)viewController withBarButtonItem:(UIBarButtonItem *)barButtonItem forPopoverController:(UIPopoverController *)newpopoverController
{
self.showMasterViewButton = [[UIBarButtonItem alloc]initWithTitle:nil style:UIBarButtonItemStyleDone target:barButtonItem.target action:barButtonItem.action];
}
First observation here is that the button is actually available in both 5.0 and 5.1 and shows and works on the nav bar. However referencing the same button in code causes the crash on 5.0 and works on 5.1. I don't know why.
Same issue for hiding it in ios 5.0. in iOS 5.1 is use this approach:
if (self.masterPopoverController) {
[self.masterPopoverController dismissPopoverAnimated:YES];
}
self.masterPopoverController is set in the same splitview delegate callback listed above. this works perfect in iOS 5.1 but does nothing in iOS 5.0
NOTE - UPDATED: I found an answer here to resolve the first issue I listed: https://github.com/mattgemmell/MGSplitViewController/pull/31 to fix the first issue I listed.
//grab a reference to the popover controller in the split view delegate call
//splitview ... willHideViewController
self.masterPopoverController = popoverController;
//then add the following to a method and call it when you need it
//this fixes the no window issue in iOS 5.0
[self.masterPopoverController presentPopoverFromRect:CGRectZero inView:[[UIApplication sharedApplication] keyWindow] permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
I must have missed this, but I'm assuming apple did this on purpose, but there must be a way to override?
NOTE: found a resolution or at least a way to emulate ios5.0 behavior on ios5.1
create a property to hold a UIViewController and another one to hold a UIPopoverController
then in the split view delegate callback grab a copy of the master view controller
- (void)splitViewController:(UISplitViewController *)splitController willHideViewController:(UIViewController *)viewController withBarButtonItem:(UIBarButtonItem *)barButtonItem forPopoverController:(UIPopoverController *)newpopoverController {
self.copyOfMasterViewController = viewController;
}
then add a method to your project like this:
-(void)showsPopover {
self.ios51popover = [[UIPopoverController alloc]initWithContentViewController:self.masterViewInPopover];
[self.ios51popover setPopoverContentSize:CGSizeMake(320, 580) animated:NO];
[self.ios51popover presentPopoverFromRect:CGRectMake(50, 55, 1, 1) inView: [[UIApplication sharedApplication] keyWindow] permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
}
-(void)hidesPopover { [self.ios51popover dismissPopoverAnimated:YES]; }
now, you have have both.
This first snippet shows how to display the popover in a split view programmatically that works in ios5.0 and 5.1 and fixes the Popovers cannot be presented from a view without a window. NOTE - UPDATED: I found an answer here to resolve the first issue I listed: https://github.com/mattgemmell/MGSplitViewController/pull/31 to fix the first issue I listed.
//grab a reference to the popover controller in the split view delegate call //splitview ... willHideViewController
self.masterPopoverController = popoverController;
//then add the following to a method and call it when you need it //this fixes the no window issue in iOS 5.0 [self.masterPopoverController presentPopoverFromRect:CGRectZero inView:[[UIApplication sharedApplication] keyWindow] permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
This next snippet shows how to present a real popover in the ios5.0 style rather than the slide in effect apple went to in iOS 5.1
NOTE: UPDATED: found a resolution or at least a way to emulate ios5.0 behavior on ios5.1 create a property to hold a UIViewController and another one to hold a UIPopoverController
then in the split view delegate callback grab a copy of the master view controller
- (void)splitViewController:(UISplitViewController *)splitController willHideViewController:(UIViewController *)viewController withBarButtonItem:(UIBarButtonItem *)barButtonItem forPopoverController:(UIPopoverController *)newpopoverController {
self.copyOfMasterViewController = viewController;
}
then add a method to your project like this:
-(void)showsPopover {
self.ios51popover = [[UIPopoverController alloc]initWithContentViewController:self.copyOfMasterViewController];
[self.ios51popover setPopoverContentSize:CGSizeMake(320, 580) animated:NO];
[self.ios51popover presentPopoverFromRect:CGRectMake(50, 55, 1, 1) inView: [[UIApplication sharedApplication] keyWindow] permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
}
-(void)hidesPopover { [self.ios51popover dismissPopoverAnimated:YES]; }