Reputation: 700
I am hoping I can describe this situation correctly. It is easy to see on the screen when it is happening, but hard to explain in words, but I will do my best.
I have a UISplitViewController with a fixed Master view (UITableView) and one of two Detail views, depending on what kind of cell is touched in the Master. Each of the Detail views is also a UITableView. I have used Todd Bates conversion of Apple's MultipleDetailViews sample to using storyboards as the basis for my code (Adventures in UISplitViewController).
I am using storyboards, so this is where the explaining part gets tricky. The Master and the first displayed Detail view Navigation Controllers are wired up in the storyboard as Relationships to the UISplitViewController. The second Detail Navigation Controller is just sitting in the storyboard with no connections.
Here's the problem. Detail #1 is active in landscape mode and Detail #2 is set as active by tapping a row in the Master. The iPad is rotated to Portrait mode which causes Detail #2 to resize properly for portrait mode. Detail #1 is set as active by tapping a row in the Master. Detail #1 is the same size as it was when it was last displayed in landscape mode, it doesn't fill the screen like it should.
My question is, can I tell the Detail controller that is not currently displayed to resize itself when the orientation is changed? Or maybe a better question is how can I resize the Detail view that was just displayed to fill the Detail portion of the UISplitView?
I hope I described this with enough detail for someone to help.
The UISplitViewControllerDelegate methods are implemented in a Manager class that's supposed to forward those calls to the Detail view controllers. Here's the implementation for that method:
#pragma mark - UISplitViewControllerDelegate
/* forward the message to the current detail view
* all detail views must implement UISplitViewControllerDelegate
*/
-(void)splitViewController:(UISplitViewController *)svc willHideViewController:(UIViewController *)aViewController withBarButtonItem:(UIBarButtonItem *)barButtonItem forPopoverController:(UIPopoverController *)pc
{
self.masterBarButtonItem = barButtonItem;
self.masterPopoverController = pc;
barButtonItem.title = NSLocalizedString(@"Games", @"Games");
[self.currentDetailController.navigationItem setLeftBarButtonItem:self.masterBarButtonItem animated:YES];
}
/* forward the message to the current detail view
* all detail views must implement UISplitViewControllerDelegate
*/
-(void)splitViewController:(UISplitViewController *)svc willShowViewController:(UIViewController *)aViewController invalidatingBarButtonItem:(UIBarButtonItem *)barButtonItem
{
self.masterBarButtonItem = nil;
self.masterPopoverController = nil;
[self.currentDetailController.navigationItem setLeftBarButtonItem:nil animated:YES];
}
And I have implemented the following in each one of the Detail view controllers:
#pragma mark - Split view
- (void)splitViewController:(UISplitViewController *)splitController willHideViewController:(UIViewController *)viewController withBarButtonItem:(UIBarButtonItem *)barButtonItem forPopoverController:(UIPopoverController *)popoverController
{
barButtonItem.title = NSLocalizedString(@"Games", @"Games");
[self.navigationItem setLeftBarButtonItem:barButtonItem animated:YES];
self.masterPopoverController = popoverController;
}
- (void)splitViewController:(UISplitViewController *)splitController willShowViewController:(UIViewController *)viewController invalidatingBarButtonItem:(UIBarButtonItem *)barButtonItem
{
// Called when the view is shown again in the split view, invalidating the button and popover controller.
[self.navigationItem setLeftBarButtonItem:nil animated:YES];
self.masterPopoverController = nil;
}
Problem is that neither of the Detail view controllers are receiving these messages. I can't see how they's get triggered anyway...
I don't see how forwarding the didRotateFromInterfaceOrientation: will cause the Detail controller that is not displayed from resizing itself. From Apple's documentation:
When the orientation of an iOS–based device changes, the system sends out a UIDeviceOrientationDidChangeNotification notification to let any interested parties know that the change occurred. By default, the UIKit framework intercepts this notification and uses it to update your interface orientation automatically. This means that, with only a few exceptions, you should not need to handle this notification at all. Instead, all you need to do is implement the appropriate methods in your view controller classes to respond to orientation changes.
The window object does much of the work associated with changing the current orientation. However, it works in conjunction with the root view controller to determine whether an orientation change should occur at all and, if so, what additional methods should be called to respond to the change. If this controller is a container, it may rely on a child to decide whether the orientation should occur.
When a rotation occurs, methods of the view controller are called at various stages of the rotation to give the view controller a chance to perform additional tasks. You might use these methods to hide or show views, reposition or resize views, or notify other parts of your app about the orientation change. Because your custom methods are called during the rotation operation, you should avoid performing any time-consuming operations there. You should also avoid replacing your entire view hierarchy with a new set of views. There are better ways to provide unique views for different orientations, such as presenting a new view controller (as described in “Creating an Alternate Landscape Interface”).
Upvotes: 3
Views: 3295
Reputation: 700
I ended up solving my own problem. In the code that swaps the Detail views, I set the view about to be displayed to the same size as the view that was just displayed. I still have further testing to do, but this solution looks like a winner.
Upvotes: 1
Reputation: 25740
Similar to the splitViewController methods, you should forward the following call:
- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation {
[super didRotateFromInterfaceOrientation:fromInterfaceOrientation];
// Forward to detail view controller here:
}
to the detail view controller that is NOT visible (i.e. NOT self.currentDetailController, but the other one).
Upvotes: 1