自iOS5引入Storyboard以後,iOS開發者在除了原有的Nib開發的基礎上又有了新的方式來組織本身的UI和流程。Storyboard相對於傳統的Nib,可以更加清晰的體現業務的流程,所以很受開發者歡迎。現在,不少教程都以Storyboard開發方式來說解。而Storyboard中的Segue則是對轉場流程的進一步封裝。這個概念在Storyboard中相當重要,也是實現自定義轉場的關鍵角色。ios
自定義Segue的方式很簡單,只要建立一個UIStoryboardSegue子類,並實現其perform
方法便可。一個簡單的實現以下:框架
- (void)perform { // Modal presentation segue UIViewController *fromController = self.sourceViewController; UIViewController *toController = self.destinationViewController; [fromController presentViewController:toController animated:YES completion:^{ // Completion code here }]; }
或者ide
- (void)perform { // Navigation ViewController segue(Push segue, Show segue in iOS8). UIViewController *fromController = self.sourceViewController; UIViewController *toController = self.destinationViewController; [fromController.navigationController pushViewController:toController animated:YES]; }
自定義Unwind Segue的方式與上面幾乎徹底同樣,只不過調用的接口由presentViewController:animated:completion:
和pushViewController:animated:
換成dismissViewControllerAnimated:completion:
和popToViewController:animated:
。
可是Unwind Segue與普通的Segue有一個很大的不一樣,就是Unwind Segue的調用一般是由一個Container View Controller完成的。在iOS SDK的UIKit框架中,Navigation View Controller和TabBar View Controller都是經常使用的Container View Controller。ui
那麼爲何Unwind Segue須要一個Container View Controllerl的支持?設計
這裏就須要提一下Unwind Segue的設計初衷及其工做方式。之因此引入Unwind Segue,是爲了應付任意跳轉的狀況,即從任意一個View Controller轉場到特定的View Controller。在Nib的時代,這種工做每每經過delegate來完成。可是有了Unwind Segue之後,咱們只要在須要跳轉到的這個特定的View Controller類中實現一個簽名爲- (IBAction)unwindMethod:(UIStoryboardSegue *)segue
這樣的方法便可(其中unwindMethod能夠替換爲任何你喜歡的名稱,但注意,當存在多個這樣的方法時,名稱不要相同,以避免發生衝突,形成不可預料的後果)。這樣,咱們就能夠在任意的View Controller(除了含有這個方法自己的View Controller)經過鏈接Segue來實現任意View Controller跳轉到當前View Controller。不用再多寫一行代碼,這些均可以經過Interface Builder搞定,很是方便。code
Unwind Segue的工做原理大體以下1:orm
performSegueWithIdentifier:sender:
方法觸發一個Unwind Segue之後,首先UIKit會發送canPerformUnwindSegueAction:fromViewController:withSender:
消息到sourceViewController
詢問是否處理UnwindSegue的action,因爲sourceViewController
不能處理(Unwind到自身沒有意義),會返回NOsourceViewController
的父Controller。若是sourceController是嵌入Navigation View Controller的子Controller,那麼父Controller就是其navigationControllerviewControllerForUnwindSegueAction:fromViewController:withSender:
消息給navigationController,詢問可否找到一個負責處理此action的子ControllerviewControllerForUnwindSegueAction:fromViewController:withSender:
實現中,navigationController會向本身的navigation棧上的全部子Controller發送canPerformUnwindSegueAction:fromViewController:withSender:
消息。UIViewController
類中,該方法的默認實現會查看unwinde segue action定義是否存在(即上面提到的特定簽名的方法是否存在,這個方法的內部實現能夠留空),若存在就返回YES。viewControllerForUnwindSegueAction:fromViewController:withSender:
方法返回nil,則不會觸發任何Unwind SeguesegueForUnwindingToViewController:fromViewController:identifier:
消息給navigationController,此方法將返回一個實際執行定製轉場的segue實例sourceViewController
上的prepareForSegue:sender:
方法viewControllerForUnwindSegueAction:fromViewController:withSender:
方法返回的destinationViewController
中的Segue action方法perform
方法從上面的咱們能夠知道,Unwind Segue的正常工做必需要有一個Container View Controller做爲全部流程View Controller的父Controller來管理整個流程。在上面的原理說明中,這個父Controller是Navigation View Controller。若是咱們要實現一個本身的定義的Container,就必須給自定義的View Controller類實現一些上面提到過的方法:教程
canPerformUnwindSegueAction:fromViewController:withSender:
viewControllerForUnwindSegueAction:fromViewController:withSender:
segueForUnwindingToViewController:fromViewController:identifier:
關於這些方法的說明和實現方式,我將在下一篇文章中詳細討論。接口
參考iOS6 by Tutorial ↩事件