强制隐藏详细视图后未调用 UISplitViewController willHideViewController/willShowViewController

发布于 2025-01-07 23:46:24 字数 2756 浏览 0 评论 0原文

我有一个 iPad 应用程序,它使用 UISplitViewController 作为根控制器,我已经设置了委托,并且我正在使用 UINavigationController 作为 DetailView,它似乎工作正常。

当特定视图控制器显示在 DetailView 部分中时,我希望 MasterViewContoller 始终隐藏(在所有旋转中)。我可以使用 UISplitViewController 委托上的 shouldHideViewController 方法来执行此操作。

但是,如果我这样做,那么当我将 DetailView 部分中的 ViewController 更改为另一个时,会显示 MasterView,但委托中不会调用 willHideViewController/willShowViewController 。

如果我旋转设备并旋转回来,它们就会被调用并且它会按预期工作,但直到设备旋转并旋转回原始方向后才会调用它们。

这会导致在显示 MasterView 后第一次旋转时不显示弹出按钮。

- (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;
    }

}

}

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;
    }

}

}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

栖竹 2025-01-14 23:46:24

我遇到了一个非常类似的问题,使用 Apple 的示例代码和 SubstitutableDetailViewController 委托与旋转相结合。

我所做的是在方向为横向时存储一个 BOOL,并使用以下代码在 willRotateToInterfaceOrientation 上更新它:

isLandscape = UIInterfaceOrientationIsLandscape(self.interfaceOrientation);

viewWillAppear 上我检查了当前方向是否为横向,如果与存储的值不匹配,则调用此方法:

-(void)adjustLayoutForOrientation{
    if (isLandscape) {
        [self invalidateRootPopoverButtonItem:  self.navigationController.navigationItem.leftBarButtonItem];
}else{
        LeftViewController *lvc = (LeftViewController *)[self.splitViewController delegate];
        [self showRootPopoverButtonItem:  lvc.rootPopoverButtonItem ];
    }
}

显然我正在使用委托代码由 Apple 提供,但为了完整起见,这些方法如下,并且可以轻松实现:

#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];
}

主视图控制器(左侧)维护对 rootPopoverButtonItem 的引用,这使得这项工作有效。

编辑:请注意,我还在 viewDidLoadwillRotateToInterfaceOrientation 上调用我的 adjustLayoutForOrientation 方法...更好的方法可能是向通知中心注册,但我不确定背景/不可见视图控制器是否会收到这些通知......

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...

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文