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

Nex*_*Nex 6 iphone uiviewcontroller ipad uisplitviewcontroller

我试图在UISplitViewController中更改主视图控制器(以纵向显示在popover中,在横向中显示在左侧).我想在主视图控制器之间切换,它是两个不同的UIViewControllers之一(取决于我的应用程序中的其他地方采取的操作).

我使用以下内容:

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

这正确地改变了主视图控制器,就像在横向模式下一样.但是它似乎没有更改用于纵向模式中的弹出框的视图控制器.

我注意到显示这个主视图控制器的barbuttonitem只是在splitviewcontroller上调用showMasterInPopover:因此它也期望它在纵向模式下工作,但事实并非如此.

实际上,我可以设置主视图控制器,在横向模式下正确查看新的 viewController,旋转纵向,并且弹出窗口中使用的视图控制器仍然是旧的.

这是一个错误吗?

occ*_*lus 1

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

我们刚刚遇到了完全相同的问题。有时我想知道苹果是否真的用类似实际用例的东西测试了他们编写的类,因为 UISplitViewController 并不是他们最好的时刻。

问题是,当您替换分割视图中的主视图控制器时,UISplitViewController 内的代码不会更新其弹出控制器的 contentViewController 属性。结果是,弹出窗口控制器仍然拥有过时视图控制器的句柄,导致在纵向模式下出现旧的 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];       
}
Run Code Online (Sandbox Code Playgroud)

当您的 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];
Run Code Online (Sandbox Code Playgroud)

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

更新

上面的方案,通过设置内容视图,最终证明是行不通的。例如,如果您将内容视图设置为 uinavigationcontroller,则稍后您将传递导航控制器内的根视图,而不是导航控制器本身。据我所知, UISplitViewController 只是不以任何可行的方式处理更改主视图。

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

更新2

我放弃。上面第一次更新中的方法也有缺陷;我在旋转时仍然遇到问题。基本上,如果您使用 UISplitViewController,您不应该尝试对主视图控制器进行任何更改(即使您在主视图(例如作为弹出窗口)再次隐藏时切换主视图)。在主视图中摆弄 UINavigationController 的内容(当主视图显示时)看起来好像没问题,但除此之外的任何事情都会导致一个又一个问题。

技术说明:我认为这些问题源于Apple处理UI的明显弱点:即,一旦隐藏或从视图中删除,Apple代码将调用UIViews和控制器上的release,但稍后,如果再次显示包含的viewcontroller,则发送延迟消息(如 viewDidDisappear)到已释放的视图/控制器(此时可能已被释放)。