🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
[TOC=5] >原文链接 :[Using Segues](https://developer.apple.com/library/content/featuredarticles/ViewControllerPGforiPhoneOS/UsingSegues.html#//apple_ref/doc/uid/TP40007457-CH15-SW1) 使用 Segue 来定义应用程序界面的流程。 Segue 定义了应用程序故事板文件中两个视图控制器之间的转换。 Segue 的起始点是启动 Segue 的按钮,列表或手势。 Segue 的结束点是想要显示的视图控制器。 Segue 总是呈现一个新的视图控制器,但是也可以使用 unwind segue 来关闭视图控制器。 ###### 图 9-1 两个视图控制器之间的 Segue ![](https://developer.apple.com/library/content/featuredarticles/ViewControllerPGforiPhoneOS/Art/segue_defined_2x.png) 不需要以编程的方式触发 Segue 。 在运行时, UIKit 加载与视图控制器相关联的 segues ,并将它们连接到相应的元素。 当用户与元素进行交互时, UIKit 会加载相应的视图控制器,通知您的应用程序即将发生的事件,并执行转换。 可以使用 UIKit 发送的通知将数据传递到新的视图控制器,或者或者阻止 segue 的执行。 ### 在视图控制器之间创建一个 Segue 要在同一个故事板文件中的视图控制器之间创建一个 Segue,请按住 Control 键单击第一个视图控制器中的相应元素,然后拖动到目标视图控制器。 Segue 的起始点必须是具有已定义操作的视图或对象,例如 control,bar button item 或 gesture recognizer 。 也可以从基于单元格的视图(如 UITableView 和 UICollectionView)创建 Segue。 图 9-2 显示了创建一个 Segue,当一个列表被点击时显示一个新的视图控制器。 ###### 图 9-2 创建 Segue ![](https://developer.apple.com/library/content/featuredarticles/ViewControllerPGforiPhoneOS/Art/segue_creating_2x.png) > 注意 一些元素支持多个 Segue 。例如,一个 UITableViewCell 拥有多个可以点击的控件允许您配置不同的 Segue 。 当释放鼠标按钮时,Interface Builder 会提示选择要在两个视图控制器之间创建的关系类型,如图 9-3 所示。 选择与您想要的转换相对应的 Segue 。 ###### 图9-3选择要创建的 Segue 的类型 ![](https://developer.apple.com/library/content/featuredarticles/ViewControllerPGforiPhoneOS/Art/segue_creating_relationships_2x.png) 在选择 Segue 的关系类型时,尽量选择一个自适应的 Segue 。自适应的 Segue 根据当前环境自动调整它们的行为。例如,`Show` segue 的行为基于呈现中的视图控制器。iOS 7 不支持自适应的 Segue,但它也提供了非自适应的 Segue 。表 9-1 列出了自适应的 Segue 以及它们在应用程序中的行为。 ###### 表 9-1 自适应 Segue 类型 | Segue 类型 | 行为 | | --- | --- | | Show (Push) | Segue 使用源视图控制器的 `showViewController:sender:` 方法显示新的内容。 对于大多数视图控制器,这个 Segue 在源视图控制器上以弹出方式呈现新的内容。 一些视图控制器专门覆盖重写该方法并使用它来实现不同的行为。 例如,导航控制器将新的视图控制器推到其导航堆栈上。UIKit 使用 `targetViewControllerForAction:sender:` 方法来定位源视图控制器。 | | Show Detail (Replace) | Segue 使用源视图控制器的 `showDetailViewController:sender:` 方法显示新的内容。 这个 Segue 仅与嵌入在 UISplitViewController 对象内的视图控制器有关。 通过这个 Segue,UISplitViewController 用新的内容替换它的第二个子视图控制器(detail controller)。 大多数其他视图控制器以弹出方式呈现新内容。UIKit 使用 `targetViewControllerForAction:sender:` 方法来定位源视图控制器。 | | Present Modally | Segue 使用指定的显示和转换样式显示视图控制器。定义显示上下文的视图控制器处理实际的显示效果。 | | Present as Popover | 在水平的常规环境中,视图控制器出现在弹出窗口中。 在水平紧凑的环境中,视图控制器使用全屏模式显示。 | 创建一个 Segue 后,选择 Segue 对象并使用属性检查器为其指定一个标识符。 在 Segue 期间,可以使用标识符来确定哪个 Segue 被触发,如果您的视图控制器支持多个 Segue,这是特别有用的。 标识符包含在执行 Segue 时交付给视图控制器的 UIStoryboardSegue 对象中。 ### 在运行时修改 Segue 的行为 图 9-4 显示了当一个 Segue 被触发时会发生什么。 大多数工作发生在呈现视图控制器中,该视图控制器管理新视图控制器的转换。 新视图控制器的配置基本上与自己创建视图控制器并呈现它的过程基本相同。 由于从故事板配置了 segues,因此参与 Segue 的两个视图控制器必须位于同一个故事板中。 ###### 图 9-4 使用 Segue 显示视图控制器 ![](https://developer.apple.com/library/content/featuredarticles/ViewControllerPGforiPhoneOS/Art/VCPG_displaying-view-controller-using-segue_9-4_2x.png) 在一个 Segue 中,UIKit 调用当前视图控制器的方法给你机会来影响 Segue 的结果。 * `shouldPerformSegueWithIdentifier:sender:` 方法可以让你有机会阻止 segue 发生。从这个方法中返回 NO 会导致 segue 的失败,但是不会阻止其他操作的发生。例如,UITableViewCell 的点击仍然会调用 UITableView 相关的委托方法。 * 源视图控制器的 `prepareForSegue:sender:` 方法允许将数据从源视图控制器传递到目标视图控制器。 传递给方法的 UIStoryboardSegue 对象包含对目标视图控制器的引用以及其他与 Segue 相关的信息。 ### 创造一个 Unwind Segue Unwind Segue 用来关闭已经展示的视图控制器。 通过将一个按钮或其他适当的对象链接到当前视图控制器的 Exit 对象,可以在 Interface Builder 中创建 Unwind Segue。 当用户点击按钮或与适当的对象进行交互时,UIKit 在视图控制器层次结构中搜索能够处理 Unwind Segue 的对象。然后关闭当前的视图控制器和中间视图控制器来显示 Unwind Segue 的目标视图控制器。 要创建一个 Unwind Segue : 1. 选择在 Unwind Segue 结束时出现在屏幕上的视图控制器。 2. 在您选择的视图控制器上定义一个 unwind 操作方法 ~~~ @IBAction func myUnwindAction(unwindSegue: UIStoryboardSegue) - (IBAction)myUnwindAction:(UIStoryboardSegue*)unwindSegue ~~~ 3. 导航到启动 unwind 操作的视图控制器。 4. 在你选择的视图控制器上定义一个 unwind 方法。按住 Control 键点击应该启动unwind segue 的按钮(或其他对象)。 这个元素应该在你想要关闭的视图控制器中。 5. 拖动到视图控制器场景顶部的 Exit 对象![](https://developer.apple.com/library/content/featuredarticles/ViewControllerPGforiPhoneOS/Art/segue_unwind_linking_2x.png) 6. 从关系面板中选择 unwind 方法。 在 Interface Builder 中创建相应的 Unwind Segue 之前,必须在视图控制器中定义一个 unwind 操作方法。该方法的存在是必需的,它告诉 Interface Builder,Unwind Segue 有一个有效的目标。 使用 unwind 操作方法的实现来执行应用程序的特定任务。不需要关闭 segue 中涉及到的任何视图控制器,UIKit 为你做这个。相反,使用 segue 对象获取被关闭的视图控制器,以便可以从它检索数据。还可以在 unwind segue 结束之前使用 unwind 操作来更新当前的视图控制器。 ### 以编程方式启动 Segue Segue 通常是由在故事板文件中创建的连接而触发的。然而,有时可能无法在故事板中创建 Segue,因为目标视图控制器可能还不知道。例如,游戏应用程序可能会根据游戏的结果转换到不同的场景。 在这些情况下,可以使用当前视图控制器的 `performSegueWithIdentifier:sender:` 方法从代码中以编程方式触发 Segue 。 清单 9-1 演示了从纵向到横向旋转时呈现特定视图控制器的 Segue 。 因为这种情况下的通知对象没有提供执行 Segue 命令的有用信息,视图控制器将自己指定为 Segue 的触发者。 ###### 清单 9-1 以编程方式触发一个 segue ~~~ - (void)orientationChanged:(NSNotification *)notification { UIDeviceOrientation deviceOrientation = [UIDevice currentDevice].orientation; if (UIDeviceOrientationIsLandscape(deviceOrientation) && !isShowingLandscapeView) { [self performSegueWithIdentifier:@"DisplayAlternateView" sender:self]; isShowingLandscapeView = YES; } // 剩下的例子被省略了。. } ~~~ ### 创建一个自定义 Segue Interface Builder 提供了从一个视图控制器转换到另一个视图控制器的所有标准方法 (从弹出一个视图控制器到在弹出窗口中显示一个控制器) 。 但是,如果其中没有一个 Segue 是你想要的,你可以创建一个自定义 Segue 。 #### 一个 Segue 的生命周期 要了解自定义 Segue 如何工作,您需要了解 Segue 对象的生命周期。 Segue 对象是 UIStoryboardSegue 或它的一个子类的实例。 你的 app 永远不需要直接创建 segue 对象。 当一个 segue 被触发时,UIKit创建它们。 以下是发生的事情: 1. 要呈现的视图控制器被创建并初始化。 2. Segue 对象被创建,它的 `initWithIdentifier:source:destination:` 方法被调用。 标识符是在 Interface Builder 中为 segue 提供的唯一字符串,另外两个参数表示转换中的两个控制器对象。 3. 显示中的视图控制器的 `prepareForSegue:sender:` 方法被调用。 请参阅 [Modifying a Segue’s Behavior at Runtime](https://developer.apple.com/library/content/featuredarticles/ViewControllerPGforiPhoneOS/UsingSegues.html#//apple_ref/doc/uid/TP40007457-CH15-SW11)。 4. Segue 对象的 [perform](https://developer.apple.com/documentation/uikit/uistoryboardsegue/1621912-perform) 方法被调用。 此方法执行转换以将新的视图控制器显示在屏幕上。 5. 对 Segue 的引用被释放。 #### 实现一个自定义 Segue 为了实现一个自定义的 Segue,子类 UIStoryboardSegue 并实现以下方法: * 覆盖 `initWithIdentifier:source:destination:` 方法并使用它来初始化自定义的 segue 对象。 总是先调用 `super` 方法。 * 实现 `perform` 方法并使用它来配置过渡动画。 > 注意 如果子定义实现添加了配置 Segue 的属性,则无法在 Interface Builder 中配置这些属性。 相反,在触发 Segue 的源视图控制器的 `prepareForSegue:sender:` 方法中配置自定义的 Segue 的附加属性。 清单 9-2 显示了一个非常简单的自定义 Segue 。这个例子简单地展示了如何弹出目标视图控制器,没有任何动画,但是您可以根据需要扩展这个想法。 ###### 清单 9-2 一个自定义的 Segue ~~~ - (void)perform { // 在这里添加自己的动画代码。 [[self sourceViewController] presentViewController:[self destinationViewController] animated:NO completion:nil]; } ~~~