ios - 如何在不显示中间 View 的情况下展开多个 View

标签 ios objective-c iphone xcode uistoryboardsegue

假设我们有三个 View Controller :1、2 和 3。使用 Storyboard,使用展开转场从 View Controller 3 展开到 View Controller 1 非常简单。但是,展开时, View Controller 2 在显示 View Controller 1 之前短暂可见。有什么办法可以让 3 变成 1 而不再显示 2 吗?

View Controller 1:

- (void)viewDidAppear:(BOOL)animated {
  [super viewDidAppear:animated];
  NSLog(@"one did appear");
}

- (IBAction)goToTwo:(id)sender {
  NSLog(@"#### segue to two");
  [self performSegueWithIdentifier:@"TwoSegue" sender:self];
}

- (IBAction)unwindToOne:(UIStoryboardSegue *)sender {
}

View Controller 2:

- (void)viewDidAppear:(BOOL)animated {
  [super viewDidAppear:animated];
  NSLog(@"two did appear");
}
- (IBAction)goToThree:(id)sender {
  NSLog(@"#### segue to three");
  [self performSegueWithIdentifier:@"ThreeSegue" sender:self];
}

View Controller 3:

- (void)viewDidAppear:(BOOL)animated {
  [super viewDidAppear:animated];
  NSLog(@"three did appear");
}

- (IBAction)unwindToOne:(id)sender {
  NSLog(@"#### unwind to one");
  [self performSegueWithIdentifier:@"OneSegue" sender:self];
}

这会产生以下日志消息:

  • 一个确实出现了
  • 转到两个
  • 确实出现了两个
  • 转到三
  • 确实出现了三个
  • 放松一下
  • 确实出现了两个
  • 一个确实出现了

我试过使用自定义转场和禁用动画。尽管移除动画会使 View Controller 2 出现的时间更短,但它仍然会出现。有什么方法可以对这种行为进行编程吗?

Storyboard截图:

enter image description here

最佳答案

这似乎是由于 unwind segues 搜索最近的 View Controller 的方式,该 View Controller 实现了您在 Storyboard 中指定的展开操作。来自 the documentation :

How an Unwind Segue Selects its Destination

When an unwind segue is triggered, it must locate the nearest view controller that implements the unwind action specified when the unwind segue was defined. This view controller becomes the destination of the unwind segue. If no suitable view controller is found, the unwind segue is aborted. The search order is as follows:

A viewControllerForUnwindSegueAction:fromViewController:withSender: message is sent to the parent of the source view controller.

A viewControllerForUnwindSegueAction:fromViewController:withSender: message is sent to the next parent view controller [...]

You can override canPerformUnwindSegueAction:fromViewController:withSender: if you have specific requirements for whether your view controller should handle an unwind action.

您的示例中的 View Controller 没有父级,所以看来回退(我看不到文档)是实例化每个 presentingViewController 并依次调用它们的 canPerformUnwindSegueAction。从 ViewControllerTwo 中的此方法返回 NO 不会阻止其实例化和显示,因此无法解决问题。

我试过将您的代码嵌入到导航 Controller 中,效果很好。这是因为在这种情况下,UINavigationController 是每个 View Controller 的父级,它处理目标 View Controller 的所有选择。更多文档:

Container View Controllers

Container view controllers have two responsibilities in the unwind process, both discussed below. If you are using the container view controllers provided by the SDK, such as UINavigationController, these are handled automatically.

如果您要创建一个简单的容器 View Controller 作为您的三个 View Controller 的父级,您可以使用它的 viewControllerForUnwindSegueAction 方法来检查它的每个子 Controller 是否存在展开操作,在该 Controller 上调用 canPerformUnwindSegueAction 之前,最后返回返回 YES 的第一个。

Selecting a Child View Controller to Handle An Unwind Action

As mentioned in How an Unwind Segue Selects its Destination, the source view controller of an unwind segue defers to its parent to locate a view controller that wants to handle the unwind action. Your container view controller should override the method shown in Listing 2 to search its child view controllers for a view controller that wants to handle the unwind action. If none of a container's child view controllers want to handle the unwind action, it should invoke the super's implementation and return the result.

A container view controller should search its children in a way that makes sense for that container. For example, UINavigationController searches backwards through its viewControllers array, starting from the view at the top of the navigation stack.

Listing 2 Override this method to return a view controller that wants to handle the unwind action. - (UIViewController *)viewControllerForUnwindSegueAction:(SEL)action fromViewController:(UIViewController *)fromViewController withSender:(id)sender

容器 View Controller 设计有一个 whole article Apple 致力于它,我不会在这里重复(Apple 已经在这个答案中写得足够多了!)但看起来需要一些思考才能让它正确,因为它取决于你想要这些的确切角色在您的应用程序中播放。

一个快速的变通方法,为了使用 unwind segues 获得你想要的行为,可以将 View Controller 嵌入到 UINavigationController 中,然后使用隐藏导航栏

[self.navigationController setNavigationBarHidden:YES];

关于ios - 如何在不显示中间 View 的情况下展开多个 View ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26785511/

相关文章:

objective-c - 使用最简单的方法将数据(字符串)从子 VC 传递到父 VC

iphone - 无法根据 xib 中的按钮更新 UIView 中的 UIImage 变量

javascript - 访问 iPhone GPS 坐标

iphone - 仍然对 Objective C 中的内存管理感到好奇

ios - 当 CNContact 保存联系人时联系人图像不发送

ios - 线程 1 : signal SIGABRT in JSONSerialization

ios - 在 IOS 中构建一个使用 node.js 服务器的聊天应用程序

ios - 无法在 HOME.VC 文本标签中显示 JSON 结果

ios - 如何隐藏 iOS 图表饼图中的值?

ios - UISearchBar 的取消和清除按钮在 iOS 7 中不起作用