iOS中的轉場研究(2)

自iOS5引入Storyboard以後,iOS開發者在除了原有的Nib開發的基礎上又有了新的方式來組織本身的UI和流程。Storyboard相對於傳統的Nib,可以更加清晰的體現業務的流程,所以很受開發者歡迎。現在,不少教程都以Storyboard開發方式來說解。而Storyboard中的Segue則是對轉場流程的進一步封裝。這個概念在Storyboard中相當重要,也是實現自定義轉場的關鍵角色。ios

自定義Segue

自定義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

自定義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的工做原理大體以下1orm

  • 當咱們經過UI事件或手動調用performSegueWithIdentifier:sender:方法觸發一個Unwind Segue之後,首先UIKit會發送canPerformUnwindSegueAction:fromViewController:withSender:消息到sourceViewController詢問是否處理UnwindSegue的action,因爲sourceViewController不能處理(Unwind到自身沒有意義),會返回NO
  • UIKit而後會尋找sourceViewController的父Controller。若是sourceController是嵌入Navigation View Controller的子Controller,那麼父Controller就是其navigationController
  • 以後UIKit會發送viewControllerForUnwindSegueAction:fromViewController:withSender:消息給navigationController,詢問可否找到一個負責處理此action的子Controller
  • 在navigationController的默認viewControllerForUnwindSegueAction:fromViewController:withSender:實現中,navigationController會向本身的navigation棧上的全部子Controller發送canPerformUnwindSegueAction:fromViewController:withSender:消息。UIViewController類中,該方法的默認實現會查看unwinde segue action定義是否存在(即上面提到的特定簽名的方法是否存在,這個方法的內部實現能夠留空),若存在就返回YES。
  • 若是navigationController的viewControllerForUnwindSegueAction:fromViewController:withSender:方法返回nil,則不會觸發任何Unwind Segue
  • 若是navgationController找到一個子類能夠處理Unwind Segue的action,那麼UIKit會發送segueForUnwindingToViewController:fromViewController:identifier:消息給navigationController,此方法將返回一個實際執行定製轉場的segue實例
  • 調用sourceViewController上的prepareForSegue:sender:方法
  • 調用由viewControllerForUnwindSegueAction:fromViewController:withSender:方法返回的destinationViewController中的Segue action方法
  • 調用Unwind Segue實例中的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:

關於這些方法的說明和實現方式,我將在下一篇文章中詳細討論。接口


  1. 參考iOS6 by Tutorial 事件

相關文章
相關標籤/搜索