UISplitViewController无法更改主视图控制器?

6
我试图更改UISplitViewController中主视图控制器(在纵向时出现在弹出窗口中,在横向时出现在左侧),我想在两个不同的UIViewControllers之间切换主视图控制器(取决于应用程序中其他地方采取的操作)。
我正在使用以下代码:
mySplitViewController.viewControllers = [NSArray arrayWithObjects:newMasterController, detailController, nil];
这将正确地更改主视图控制器,如您在横向模式下所期望的那样。但是在纵向模式下似乎没有更改用于弹出窗口的视图控制器。
我注意到显示此主视图控制器的barbuttonitem只是在splitviewcontroller上调用showMasterInPopover:,因此也希望它在纵向模式下工作,但实际上并没有。
事实上,我可以设置主视图控制器,看到新的视图控制器在横向模式下正确,旋转回纵向模式后,用于弹出窗口的视图控制器仍然是旧的。
这是一个错误吗?
2个回答

2
如果有人正在寻找解决此问题的方案(或变通方法),我也遇到了类似的问题,并在这里解决了: 更改分屏视图中的主视图不会更新纵向模式下的弹出窗口
基本上,我为主视图控制器使用了一个导航控制器,并在该导航控制器内推送/弹出视图控制器,以便在仍然在弹出视图中显示正确的视图控制器的情况下更改主视图中的视图控制器。

1

更新:请阅读底部的最终更新!下面的原始答案和更新可能没有用处!

我们刚刚遇到了完全相同的问题。有时我会想,苹果是否真正测试过他们编写的类与任何类似于现实使用情况的东西,因为UISplitViewController并不是他们最好的时刻。

问题在于,当您替换分割视图中的主视图控制器时,UISplitViewController内部的代码不会更新其popover控制器的contentViewController属性。结果是,popover控制器仍然持有一个过时的视图控制器句柄,导致旧的UI出现,甚至在纵向模式下出现内存故障。

这是我们的解决方法。

我假设您有一个UISplitViewControllerDelegate符合类,该类将popoverController作为类属性存储(请参见UISplitViewController的标准示例代码)。

在设置新的主视图控制器的时候,您还需要更新contentViewController,如下所示:

mySplitViewController.viewControllers
    = [NSArray arrayWithObjects:newMasterController, detailController, nil];

// in the cases where the uisplitview has already shown a popovercontroller,
// we force the popovercontroller to update its content view controller. 
// This ensures any old content view in popover actually gets released by 
// the popovercontroller.
if (popoverController) {
    [popoverController setContentViewController:theMasterViewController 
                                animated:NO];       
}

当您的UISplitViewControllerDelegate被告知弹出控制器将要呈现视图控制器时,您还必须设置弹出窗口的contentViewController:
- (void)splitViewController:(UISplitViewController*)svc 
        popoverController:(UIPopoverController*)pc 
        willPresentViewController:(UIViewController *)aViewController 
{
    // set the popoverController property - as per Apple's sample code
    self.popoverController = pc;

    // THE LINE BELOW IS THE NEW LINE!
    [popoverController setContentViewController:aViewController animated:NO];

是的,我知道上面的代码看起来很疯狂,你可能会想为什么苹果不能自己设置内容视图控制器。但他们显然没有这样做,而这就是解决方法。

更新

上述方案,设置内容视图,最终证明并不奏效。例如,如果您将内容视图设置为uinavigationcontroller,稍后您会得到传递给nav控制器中的根视图,而不是nav控制器本身。UISplitViewController似乎没有以可行的方式处理更改主视图。

我当前的解决方法是安装一个UINavigationController作为主视图,并更改该导航控制器的根视图控制器。所以我可以通过“后门”改变主视图。

更新2

我放弃了。上面第一次更新的方法也有缺陷;旋转时仍然会出现问题。基本上,如果您使用UISplitViewController,则不应尝试更改主视图控制器(即使在隐藏主视图(例如作为弹出窗口)后切换主视图)。在主视图中操纵UINavigationController的内容(同时显示主视图)似乎是可以的,但超出此范围的任何操作都会导致问题。
技术说明:我认为问题源于苹果处理UI的明显弱点:即,苹果代码将在隐藏或从视图中删除UIView和控制器时调用release,但稍后,如果再次显示包含的视图控制器,则会发送延迟消息,如viewDidDisappear到已释放的视图/控制器(此时可能已被解除分配)。

UISplitViewController存在很多缺陷,其中这似乎是最糟糕的之一。即使在iOS SDK 5.1中,我仍然看到这些问题。然而,在这个版本中,使用UINavigationController作为根Master View的解决方法似乎是有效的。 - Dan F
哇,这么晚了还是这样糟糕吗?谢谢你更新我们的情况,丹。 - occulus

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接