如何解除UIStoryboard中带有模态segue的模态?

时间:2012-03-16 05:41:29

标签: cocoa-touch uistoryboard

设置:我有一个故事板设置,有两个简单的视图控制器A和B.A中有一个按钮,它转换为带有模态segue的B。 B在A之上呈现模态转换。没关系。

问题:有没有办法让B离开并用一些简单的故事板魔法回到A?

请注意,如果这一切都在导航控制器中,并且我使用了推送segue,那么导航控制器将隐含地处理它。会有一个“后退”按钮。没有类似的模态,我需要自己构建UI,这很好,但我想知道是否有一个segue机制我可以用来发信号从B回到A.

现在构建从B到A的oldskool方法将是:

  • 在B
  • 上创建委托属性
  • 当模态转换segue回放时,将A设置为B的委托(我可以使用prepareForSegue挂钩:发件人:在A的代码中)
  • 在解雇的时候,B向其代表发出信号
  • A实现一个解除B
  • 的委托方法

这很有效,但感觉太开销和愚蠢。

是否有一些我错过的UIStoryboard机制,基本上会做“反向模态”?

2 个答案:

答案 0 :(得分:44)

在没有编写至少一点代码的情况下解雇模态视图控制器没有任何故事板魔术。

但是当你必须实现自己的一些代码时,你不一定要遇到那么多麻烦。你可以在视图控制器B中有一个调用[self dismissViewControllerAnimated:YES completion:nil]的按钮。 (文档说,呈现视图控制器应该是解雇的,但他们也会说如果在出席者上调用,消息将被转发到呈现视图控制器。如果你想更明确地说明它 - 而且你'在某些情况下,例如当一个模态视图控制器出现在另一个模式视图控制器时 - 您可以使用self.presentingViewController明确引用演示者并从那里调用dismiss...。)

您在某些应用中看到了委托业务,因为它是向视图控制器A通知用户在视图控制器B中执行的任何操作的一种方式...但这不是唯一的方法。有KVO,通知,或者只是在用self.presentingViewController引用它之后简单地调用A的方法(假设B知道它总是由A呈现)。如果A不需要知道B中发生的事情(例如,因为用户点击了取消按钮),则无需执行任何操作 - 您可以解雇该模式并完成它。


在iOS 6及更高版本中,展开segues会添加另一个选项,为解雇模态视图控制器(或以其他方式“退出”一系列segue)提供一些“故事板魔术”。但是这种方法仍然需要一些代码 - 你无法在故事板中完全设置它。但是,在正面,该代码提供了一个路径,用于从视图控制器中取消信息(B)到呈现它的信息(A)。

Apple有a tech note about unwind segues详细介绍了它们,但这里是简短版本:

  1. 在要解除的视图控制器类上定义IBAction方法 - 提供模态视图控制器的方法,而不是模态视图控制器本身(视图您问题中的控制器A.与普通IBAction方法不同,这些方法应采用UIStoryboardSegue *类型的参数; e.g。

    - (IBAction)unwindToMainMenu:(UIStoryboardSegue*)sender
    
  2. 在显示的视图控制器(问题中的B)中,将控件连接到绿色的“退出”图标,然后选择您定义的方法。

  3. 在unwind方法实现中,您可以参考segue的sourceViewController来从被解除的视图控制器中检索信息。您无需调用dismissViewControllerAnimated:completion:,因为segue会处理正在消失的视图控制器。

答案 1 :(得分:30)

故事板魔术来实现这一目标。它被称为放松segue。在A的.h文件中,您可以实现任何"目标操作"您需要的风格方法,无论您需要多少解开细分。对于模态,它通常是两个(取消和保存)。所以在我的A.h文件中我会添加:

// A.h file
- (IBAction)myCancelUnwindSegueCallback:(UIStoryboardSegue *)segue;
- (IBAction)mySaveUnwindSegueCallback:(UIStoryboardSegue *)segue;

现在,在你的故事板中,如果你有一个从A到B的segue。你现在可以做一个"目标动作"样式控制从B中的取消/保存按钮拖动到绿色"退出"故事板中B控制器底部的图标。当你这样做时,Xcode将选择我们创建的两种方法(因为它们在A' s头文件中并且它们具有正确的签名(例如IBAction和UIStoryboardSegue *。)而B是a的目的地。来自A)因此,你有它。你有想要的故事板魔术!

在两个回调的实现中,您将拥有如下内容:

// A.m file
- (IBAction)myCancelUnwindSegueCallback:(UIStoryboardSegue *)segue {
    UIViewController *modalGoingAway = segue.sourceViewController;
    // Do something (like get data) from modalGoingAway if you need to...
}

- (IBAction)mySaveUnwindSegueCallback:(UIStoryboardSegue *)segue {
    UIViewController *modalGoingAway = segue.sourceViewController;
    // Do something (like get data) from modalGoingAway if you need to...
}

最后,如果这种方法满足您的需求,那就太好了。你完成了。但是,如果"取消"我仍然连接整个协议委托/ dataSource设计模式。或者"保存"我想在将控制权交给A以从视图层次结构中删除B之前,对B的私有属性执行一些操作。