UISplitViewController willHideViewController/willShowViewController not called after forcing detail view to be hidden

喜夏-厌秋 提交于 2019-12-22 18:46:30

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!