Adaptive segue in storyboard Xcode 6. Is push deprecated?

默认情况下,Xcode 6 Interface Builder 有一个新的复选框“ use size class”,它使视图具有自适应性。 enter image description here

当我试图在故事板中的两个视图之间切换时,我有了新的选择: enter image description here

而是老了:

enter image description here

现在我们有了“ show”和“ current modally”,而不是“ push”和“ mode”。旧选项被标记为已弃用。我选择了“ show”选项,因为在接下来的设置中它被称为“ show (例如 push)”

enter image description here

但是它不会推动。继续动画看起来像从底部的幻灯片(模态)和导航栏消失。

问题是: 我怎样才能使“显示”像推动一样工作?是否有可能或者我应该使用“推(弃用)”代替?我在哪里可以找到任何关于新类型的接续的信息?我在 iOS8开发者库中找到的唯一一样东西是 情节串连板帮助你设计你的用户界面,但是没有关于“ show”segue 的信息。

更新

我尝试创建新的项目和“显示”是真正的工作喜欢“推”。 我认为我的项目中的问题可能是因为我使用这样的代码重用导航控制器,但我不知道如何修复它。

if ( [segue isKindOfClass: [SWRevealViewControllerSegue class]] ) {
SWRevealViewControllerSegue *swSegue = (SWRevealViewControllerSegue*) segue;
    

swSegue.performBlock = ^(SWRevealViewControllerSegue* rvc_segue, UIViewController* svc, UIViewController* dvc) {
        

UINavigationController* navController = (UINavigationController*)self.revealViewController.frontViewController;
[navController setViewControllers: @[dvc] animated: NO ];
[self.revealViewController setFrontViewPosition: FrontViewPositionLeft animated: YES];
};
    

}

在那之后,我尝试将 NewViewController 推到 MainViewController 之后 enter image description here

更新2:

我似乎只有 iOS7,iOS7.1的问题。

75460 次浏览

是的,用“显示”代替“推”

我怎样才能使“显示”工作像推? 这是可能的还是我应该使用 而不是“推(非专用)”?

应该是的,对我来说是的。我正在使用 Xcode 6 beta 2,为了测试,我使用了单视图模板(在 IB‘ VC _ A’中调用预制的视图控制器)。然后我添加了另一个视图控制器(‘ VC _ B’)。然后我在 VC _ A 上添加了一个按钮来显示 VC _ B,另一个按钮从 VC _ B 返回到 VC _ A。当我在情节串连板中添加一个导航控制器作为初始视图控制器,并将 VC _ A 设置为 rootViewController 时,“ push”和“ show”具有相同的效果。如果我没有一个初始的导航控制器,我使用’显示’,我得到了你所描述的 VC _ B 做了一个从底部向上的幻灯片。如果我尝试“推”我得到一个崩溃,因为为了做推我必须有导航控制器。因此,在提供导航控制器的情况下,‘ show’似乎会起到推动作用,如果没有导航控制器,那么‘ show’就会以模态转换的形式呈现。

我在哪里可以找到任何关于新类型的接续的信息?

因此,我在“ Interface Builder 最新消息”课程中找到了一些信息。如果你看幻灯片,你会看到一个幻灯片(41)提到的变化。当观看会议视频时,你可以跳到38:00分钟,他们开始讨论自适应的转折点。他们的确解释了“显示”自适应的接口,例如,在决定如何展示一个新的视图控制器时考虑到了上下文。

已经有了一个公认的答案,但是我想提供更多的信息,可能是以前没有的信息。

正如前面所提到的,“推”和“模态”转折点被反对,分别被“显示”和“现在模态”所取代。根据苹果公司的文件,新的主题曲被进一步分为适合大小类的主题曲。旧版本只能用于支持比 iOS8更老的 iOS 版本。

The document in the following link explains that and the description of all the available segues, old and new.

Adding a Segue Between Scenes in a Storyboard

如果将来网址发生变化,以下是对每个新链接的解释:

表演

Present the content in the detail or master area depending on the content of the screen. If the app is displaying a master and detail view, the content is pushed onto the detail area. If the app is only displaying the master or the detail, the content is pushed on top of the current view controller stack.

展示细节

在详细区域显示内容。如果应用程序显示主视图和细节视图,新内容将替换当前细节。如果应用程序只显示主控器或细节,则内容将替换当前视图控制器堆栈的顶部。

现状

Present the content modally. There are options to choose a presentation style (UIModalPresentationStyle) and a transition style (UIModalTransitionStyle).

以爆米花的形式出现

将内容显示为锚定到现有视图的弹出窗口。还有一个选项可以指定弹出窗口视图(UIPopoverArrowDirect)边缘上显示的箭头的可能方向。还有一个指定锚视图的选项。

我知道我迟到了,但我想分享我所学到的。 这实际上是一个 bug,并且至今仍然存在(2014-12-18)。

我写了一篇关于这个 here的文章。

It is easily reproducible; on iOS8 will work just fine and even in iOS7.x as long as you don't push a view controller programmatically into the stack before calling the Show segue.

如果你只是通过故事板连接推到堆栈上,它会工作; 但显然,如果你通过代码以某种方式推,被推的 UIViewControllernavigationController属性将是 nil,当你调用 Show时,它将假设它是一个模态,因为没有导航来控制堆栈。

到目前为止,只有一种解决方案是不通过代码推送(不可行) ,或者使用现在已经废弃的 Push

我申请了一个雷达(文章上的链接)。希望苹果公司能够解决这个问题,你可以随意提交副本。

As 斯科特 · 罗伯逊评论道, this looks like a bug in iOS 7.

似乎在 iOS8中,转换是在运行时推断出来的(正确的行为) ,而在 iOS7中,转换是在设计时推断出来的(错误的行为)。

最简单的解决方案是将一个未使用的导航控制器添加到故事板中,并将其链接起来,以便所讨论的视图控制器是这个导航控制器的一部分。您实际上不需要实例化导航控制器,只需要 bug 视图控制器知道它嵌入在导航控制器中。

注意: 模拟导航栏对于这些目的是不够的; 您必须在其推送堆栈中实际拥有一个导航控制器。

为了复制这个错误:

  1. 创建一个使用大小类的新故事板。
  2. 创建两个视图控制器(没有导航控制器)。
  3. 例如,使第一视图控制器通过链接到按钮的 显示(例如推)接口显示第二视图控制器。
  4. 在代码中,显示第一个视图控制器,但通过 initWithRootViewController:方法将其嵌入到导航控制器中。
  5. 在 iOS7上运行应用程序。
  6. Tap the button that should perform the push.
  7. 你会得到一个模态转换,而不是 iOS7上的一个推。在 iOS8上,你会得到正确的推动行为。

enter image description here

要修复这个错误:

  1. 向情节串连板添加一个导航控制器,并将第一个视图控制器设置为根视图控制器。(注意: 添加第二个作为根视图控制器将不会修复此错误。)
  2. Give it a junk identifier to suppress the warning about the navigation controller being inaccessible, and to document to yourself that it exists solely as a workaround. (e.g. workaround for show segues in iOS 7).

enter image description here

注意第二张图片中是如何添加导航控制器的,以及它是如何没有任何传入箭头的(也就是说,除了使用其视图控制器标识符之外,没有其他方法来实例化它)。

我在 Xcode 7和 iOS 7.1.2中也遇到过同样的问题。 Show segues (来自 iOS 8的新特性)的工作原理类似于 IOS7中的模态切换,当你在故事板中用 Xcode 定义 segue 类型时,它不允许你将视图控制器推入导航控制器堆栈中。这就是为什么你的 self. navationController 将返回 nil,因为 View Controller 没有被推到堆栈上,你不能弹出它。

I don't understand why Apple did not add any notifications for this case in Xcode when you need your app to work on iOS 7. 他们说 Push 方法是不推荐的,但 Show 在 iOS7中不能正常工作。

我做了什么来解决这个问题:

我用.h 创建了 MYShowSegue 类

#import <UIKit/UIKit.h>


@interface MYShowSegue : UIStoryboardSegue


@end

和。 m 文件只有一个 表演方法:

#import "MYShowSegue.h"


@implementation MYShowSegue


- (void) perform {


if ([[[self sourceViewController] navigationController] respondsToSelector:@selector(showViewController:sender:)]) {


id sender = nil;
[[[self sourceViewController] navigationController] showViewController:[self destinationViewController] sender:sender];
}else{


[[[self sourceViewController] navigationController] pushViewController:[self destinationViewController] animated:YES];
}
}


@end

然后你需要设置一个 习俗类型为每个接续在你的故事板,并为它选择一个新的类,在我的情况下,它是 MYShowSegue。

自定义引导示例

这个解决方案将帮助你获得 iOS7应用程序的全面支持,他们将使用 PushViewController方法来推送你的视图,对于 iOS8,9等等,你的下一步将使用新的(iOS8)方法 ShowViewController

不要忘记在你的故事板中做同样的事情。

删除没有正确推送的 Segue,并通过从 UIView/UIControl 拖动到目标来在故事板中重新创建它 view controller.

其他的答案没有什么错,但是这个解释了正在发生的事情,你如何验证它正在发生,以及如何在将来减轻这个问题。

背景资料

In my case, none of my Show Segues were working even though I already had a UINavigationController as my initial view controller (with my content UIViewController as it's root).

Why and How the Show Segue Breaks

The Show segue breaks when it has an action associated with the segue within the storyboard's source xml. A typical scenario causing this might be if you have redefined a segue from a manual segue previously called in code. This leaves the following bits in the storyboard xml.

<connections>
<segue destination="85t-Z1-hxf" kind="show" identifier="ToOptions" action="showDetailViewController:sender:" id="gdZ-IX-KcN">
</connections>

不好 将故事板视为 xml; 右键单击故事板文件并选择 Open as > Source Code. To revert use Open as > Interface Builder - Storyboard

为了在使用故事板中的 segue 时适应任何自定义操作,只需进入 prepareForSegue 并拦截目标视图控制器并从该位置调用任何方法。在任何情况下,这个小 bug 的副作用(bug 是当你重新定义 segue 时,它没有在 xml 中正确设置,也就是说,即使在你将 segue 改为从 UIView (或 UIControl)到目标视图控制器操作的 segue 之后,操作仍然存在)。

不幸的是,最直接的解决方案失败了。因此,只要从 Storyboard 中删除操作的 xml 属性就可以解决这个问题。相反,必须在故事板中使用 简单地删除和重新创建接口

当重新创建故事板时,xml 将不再有与特定接口相关联的动作,并且 Show 将作为 Push 执行。

用于正确演示继续的示例 XML

  <connections>
<segue destination="RbV-Au-WV9" kind="show" identifier="ToOptions" id="5dm-os-bcS"/>
</connections>

Mitigation

为了防止重复,如果可能的话,只需要坚持使用非手动的情节串连接续,通过使用 prepareForSegue 基于目标视图控制器添加所需的操作。或者,如果您必须进行混合和匹配,请采取预防措施,以验证您的 Show 片段在 Storyboard xml 中没有附加任何操作。如果您正在处理较老的项目,那么您应该特别注意 Storyboard 源代码,因为我已经发现了一些问题。

这种情况在 iOS10.x 中仍在发生

删除和恢复片段接续并没有为我解决任何问题:

问题: 需要的功能是7个接口,只作为一个“推”(实际上是一个显示细节) ,但事实上只有我添加的第一个接口将推,其他都将行为模态。尽管 Interface Builder 对每个片段的描述都是一样的。

解决方案: 我必须把这个动作添加到6个没有这个动作的片段中。

原始故事板 XML

<connections>
<segue destination="tIr-4a-WfZ" kind="showDetail" identifier="A" action="showViewController:sender:" id="8yd-Ne-7KA"/>
<segue destination="4mB-YE-5dM" kind="showDetail" identifier="B" id="Uod-JC-786"/>
<segue destination="Qh5-bJ-KcE" kind="showDetail" identifier="C" id="3PW-nV-hWl"/>
<segue destination="EI6-f4-QBB" kind="showDetail" identifier="D" id="WUK-ju-KDm"/>
<segue destination="nTz-N4-fpW" kind="showDetail" identifier="E" id="Id6-bW-Huc"/>
<segue destination="JEp-CH-6dW" kind="showDetail" identifier="F" id="G0L-XW-7f4"/>
<segue destination="AET-S1-O6h" kind="showDetail" identifier="G" id="3NK-93-wTy"/>
</connections>

我通过添加 showViewController: sender 改变了这一点

<connections>
<segue destination="tIr-4a-WfZ" kind="showDetail" identifier="A" action="showViewController:sender:" id="8yd-Ne-7KA"/>
<segue destination="4mB-YE-5dM" kind="showDetail" identifier="B" action="showViewController:sender:" id="Uod-JC-786"/>
<segue destination="Qh5-bJ-KcE" kind="showDetail" identifier="C" action="showViewController:sender:" id="3PW-nV-hWl"/>
<segue destination="EI6-f4-QBB" kind="showDetail" identifier="D" action="showViewController:sender:" id="WUK-ju-KDm"/>
<segue destination="nTz-N4-fpW" kind="showDetail" identifier="E" action="showViewController:sender:" id="Id6-bW-Huc"/>
<segue destination="JEp-CH-6dW" kind="showDetail" identifier="F" action="showViewController:sender:" id="G0L-XW-7f4"/>
<segue destination="AET-S1-O6h" kind="showDetail" identifier="G" action="showViewController:sender:" id="3NK-93-wTy"/>
</connections>