【发布时间】:2016-04-13 18:53:15
【问题描述】:
我正在使用 Xcode 7(虽然我认为这也适用于 6),主从模板稍作修改。修改是将主UINavigationController替换为UITabBarController。
UITabBarController 包含几个 UINavigationController,它们又与 Detail UINavigationController 有 segues。
使用 iPhone 6+ 模拟器,它在横向模式下运行良好(非折叠)。当 UISplitViewController 折叠时,应用程序将停止按预期运行。发生了两件事:
- 在 AppDelegate 的
didFinishLaunchingWithOptions中,splitViewController.viewControllers数组包含UITabBarController(主)和UINavigationController(详细)。在didFinishLaunchingWithOptions和splitViewController:collapseSecondaryViewController:ontoPrimaryViewController之间的某个地方,详细信息UINavigationController从splitViewController.viewControllers中删除。如果 master 和 detail 都是UINavigationController对象,则不会发生这种情况。有趣的是,在 Apple 的UISplitViewController文档中,他们谈到了viewControllers属性:“展开拆分视图界面时,此属性包含两个视图控制器;当它折叠时,此属性仅包含一个视图控制器。”文档中的断言似乎仅在我修改故事板以将 UITabBarController 作为主控后才成立,在默认的主从模板中,断言不成立(即无论是否拆分视图折叠或展开)。 - 如果我在折叠模式下运行时添加项目,则详细视图会以模态方式呈现,而不是被推送到选定选项卡的导航控制器上,因此无法返回主视图。旋转到横向会导致
EXC_BAD_ACCESS崩溃 - 出于某种原因,我也收到错误消息:"<Error>: CGImageCreate: invalid image size: 0 x 0."。
在这个阶段对“vanilla”模板应用程序的唯一更改是将 Master UINavigationController 替换为包含 UINavigationControllers 的 UITabBarController,情节提要如下:
我还在MasterViewController.m 中注释掉了以下行,以防止更早的崩溃:
self.detailViewController = (DetailViewController *)[[self.splitViewController.viewControllers lastObject] topViewController];
我的问题是:
- 为什么当我将 UITabBarController 添加为主而不是保留 UINavigationController 时,
viewControllers属性的内容会发生变化?我问是因为我认为这与确定为什么细节 VC 以模态方式呈现而不是被推送有关。我假设,由于在折叠模式下,SplitViewController 的行为类似于 UINavigationController,当 UISplitViewController 和详细视图之间存在非 UINavigationController 时,这样做会有些困难。 - 从问题 1 开始,为什么细节控制器会以模态方式呈现?
我正在努力了解正在发生的事情,就像我试图找到一种正确的方法来让它工作(如果有一个(或多个)的话)。
进一步讨论及相关问题
我的问题与这个问题非常相似: UINavigationController inside a UITabBarController inside a UISplitViewController presented modally on iPhone
结合使用“Dreaming In Binary”和“HpTerm”的答案,我取得了一些成功。
如果我首先接受 Dreaming In Binary 的答案(逐字使用该答案中的代码),那么应用程序的行为几乎与以前相同;我特别注意以下几点:
-
从纵向视图中选择时,详细视图仍以模态方式呈现;由于我们添加了此方法(取自上述答案),因此基本上采用了稍微不同的详细视图呈现路径:
-(BOOL)splitViewController:(UISplitViewController *)splitViewController showDetailViewController:(UIViewController *)detailVC sender:(id)sender { UITabBarController *masterVC = splitViewController.viewControllers[0]; if (splitViewController.traitCollection.horizontalSizeClass == UIUserInterfaceSizeClassCompact) [masterVC.selectedViewController showViewController:detailVC sender:sender]; else [splitViewController setViewControllers:@[masterVC, detailVC]]; return YES; }showViewController仍然会触发 detailViewController 的模态展示。纵向右上方没有导航按钮,但是如果将设备旋转到横向,则整个横向将由详细视图获取,但我们确实看到使用 splitViewController.displayModeButton 项设置了 navigationItem 的 leftBarButtonItem。问题是该按钮除了显示“展开”按钮(用于隐藏主视图)之外绝对没有任何作用;如果您按下按钮,视图不会发生任何变化(无论如何,主视图已经隐藏)但按钮会更改为“返回”样式,这通常允许您再次显示主视图。在这种情况下,“返回”按钮在您按下时不起作用。本质上,您可以在“展开”和“返回”之间切换按钮,但按下它时没有其他效果。如果您旋转回横向,那么您将再次获得模态显示的详细视图,无法返回主视图。- 我仍然看到错误
<Error>: CGImageCreate: invalid image size: 0 x 0.,但它并未伴随 EXC_BAD_ACCESS 崩溃。
- 我仍然看到错误
接下来是 HpTerm 在 Swift 中的解决方案,在我的世界里是这样的:
- (BOOL)splitViewController:(UISplitViewController *)splitViewController showDetailViewController:(UIViewController *)detailViewController sender:(id)sender
{
UITabBarController * masterViewController = splitViewController.viewControllers[0];
if (splitViewController.traitCollection.horizontalSizeClass == UIUserInterfaceSizeClassCompact)
{
UIViewController * detailViewSubController = ((UINavigationController *)detailViewController).viewControllers[0];
[((UINavigationController *)masterViewController.selectedViewController) pushViewController:(UIViewController *)detailViewSubController animated:NO];
return YES;
}
else
{
return NO;
}
}
所以在上面,我们没有尝试使用细节的UINavigationController 来showViewController,而是从细节UINavigationController 中提取DetailViewController,并将DetailViewController 推送到主UINavigationController。没有将细节UINavigationController 推送到主控UINavigationController 的原因是抛出了异常(适用于将任何导航控制器推送到另一个控制器)。
这实际上产生了一个几乎完美的结果,但并不完全。首先,好的部分:
- 在纵向中,一切正常,我们将细节推到 掌握选择,当我们返回时,我们回到 正确掌握。
- 在旋转到横向时,拆分视图正确显示主视图和细节,我们可以使用栏按钮项正确显示/隐藏主视图。
现在不好了:
- 在旋转回纵向时(在主端选择了一个项目),我们会转到 master 视图,而实际上我们应该转到所选的详细项目。
所以这里的问题是,是否可以纠正“坏”点,以便如果在纵向选择项目时,旋转回横向将我们带到所选的详细项目?
抱歉,拖了这么久,如果你做到了这一步,我向你致敬!我也对缩小问题的建议持开放态度,但希望提供足够的细节来准确突出正在发生的事情。
【问题讨论】:
标签: ios xcode cocoa-touch