问题
I have an iPad App which uses a UISplitViewController as the root controller, I have set up the delegate and I am using a UINavigationController for the DetailView and it seems to work normally.
I want the MasterViewContoller to always be hidden (on all rotations) when a particular viewcontroller is displayed in the DetailView Section. I can do this using the shouldHideViewController method on the UISplitViewController Delegate.
However if I do, then when I change the ViewController in the DetailView Section to another the MasterView is displayed but neither willHideViewController/willShowViewController is called in the delegate.
If I rotate the device and rotate back they are called and it works as expected, but they are not called until the device has been rotated and rotated back to the original orientation.
This causes the popover button to not be displayed on the first rotation after the MasterView has been displayed.
- (void)splitViewController:(UISplitViewController*)svc willHideViewController:(UIViewController *)aViewController withBarButtonItem:(UIBarButtonItem*)barButtonItem forPopoverController:(UIPopoverController*)pc {
// Keep references to the popover controller and the popover button, and tell the detail view controller to show the button.
barButtonItem.title = @"Survey Sections";
self.popoverController = pc;
self.rootPopoverButtonItem = barButtonItem;
UIViewController <SubstitutableDetailViewController> *detailViewController = [self.splitViewController.viewControllers objectAtIndex:1];
if ([detailViewController isKindOfClass:[UINavigationController class]]) {
UINavigationController *detailNavController = (UINavigationController *)detailViewController;
[[detailNavController.viewControllers objectAtIndex:0] showRootPopoverButtonItem:rootPopoverButtonItem];
}
}
- (void)splitViewController:(UISplitViewController*)svc willShowViewController:(UIViewController *)aViewController invalidatingBarButtonItem:(UIBarButtonItem *)barButtonItem {
// Nil out references to the popover controller and the popover button, and tell the detail view controller to hide the button.
UIViewController <SubstitutableDetailViewController> *detailViewController = [self.splitViewController.viewControllers objectAtIndex:1];
if ([detailViewController isKindOfClass:[UINavigationController class]]) {
UINavigationController *detailNavController = (UINavigationController *)detailViewController;
[[detailNavController.viewControllers objectAtIndex:0] invalidateRootPopoverButtonItem:rootPopoverButtonItem];
}
self.popoverController = nil;
self.rootPopoverButtonItem = nil;
}
- (BOOL)splitViewController:(UISplitViewController *)svc shouldHideViewController:(UIViewController *)vc inOrientation:(UIInterfaceOrientation)orientation {
UIViewController *detailViewController = [svc.viewControllers objectAtIndex:1];
if ([detailViewController isMemberOfClass:[MySurveysViewController class]]) {
return YES;
}else {
if (UIInterfaceOrientationIsLandscape(orientation)) {
return NO;
}else {
return YES;
}
}
}
回答1:
I was having a very similar problem, using Apple's sample code with the SubstitutableDetailViewController
delegate combined with rotation.
What I did was store a BOOL
for when the orientation was landscape, updating it on willRotateToInterfaceOrientation
with this code:
isLandscape = UIInterfaceOrientationIsLandscape(self.interfaceOrientation);
On viewWillAppear
I checked whether the current orientation is landscape, and if it did not match the stored value, called this method:
-(void)adjustLayoutForOrientation{
if (isLandscape) {
[self invalidateRootPopoverButtonItem: self.navigationController.navigationItem.leftBarButtonItem];
}else{
LeftViewController *lvc = (LeftViewController *)[self.splitViewController delegate];
[self showRootPopoverButtonItem: lvc.rootPopoverButtonItem ];
}
}
Obviously I am using the delegation code provided by Apple, but for completeness those methods are these and can be implemented easily:
#pragma mark -
#pragma mark Managing the popover
- (void)showRootPopoverButtonItem:(UIBarButtonItem *)barButtonItem {
// Add the popover button to the left navigation item.
[self.navigationController.navigationBar.topItem setLeftBarButtonItem:barButtonItem animated:NO];
}
- (void)invalidateRootPopoverButtonItem:(UIBarButtonItem *)barButtonItem {
// Remove the popover button.
[self.navigationController.navigationBar.topItem setLeftBarButtonItem:nil animated:NO];
}
The master view controller (left side) is maintaining the reference to the rootPopoverButtonItem
, which makes this work.
EDIT: Note that I am also calling my adjustLayoutForOrientation
method on viewDidLoad
and willRotateToInterfaceOrientation
... A better way might be to register with the Notification Center but I wasn't sure if background/invisible view controllers would get these notifications...
来源:https://stackoverflow.com/questions/9411571/uisplitviewcontroller-willhideviewcontroller-willshowviewcontroller-not-called-a