Storyboard 系列文章
[iOS] Storyboard (1) -- 入門:API 篇
[iOS] Storyboard (2) --入門:約束篇
[iOS] Storyboard (3) -- 使用:常用Tips
[iOS] Storyboard (4) -- 實(shí)踐:?jiǎn)栴}總結(jié)
[iOS] Storyboard (4) -- 實(shí)踐:UIScrollView
[iOS] Storyboard (4) -- 實(shí)踐:UICollectionView
在 iOS 中有兩種可以實(shí)現(xiàn)的可視化編程的方法,一種是StoryBoard,俗稱 sb,是 iOS 下可視化編程的方式之一,另一種是 XIB。這里主要介紹和 StoryBoard 相關(guān)的一些 API。
1. UIStoryboard
UIStoryboard 的 API 很簡(jiǎn)單,主要有一個(gè)初始化方法,和兩個(gè)實(shí)例方法:
// 通過 Storyboard ID 來(lái)獲取 Storyboard 實(shí)例
+ (UIStoryboard *)storyboardWithName:(NSString *)name bundle:(nullable NSBundle *)storyboardBundleOrNil;
// 獲取當(dāng)前 Storyboard 實(shí)例的初始化控制器
- (nullable __kindof UIViewController *)instantiateInitialViewController;
// 通過 Storyboard ID 來(lái)獲取當(dāng)前 Storyboard 中的控制器實(shí)例
- (__kindof UIViewController *)instantiateViewControllerWithIdentifier:(NSString *)identifier;
如果項(xiàng)目中有多個(gè) .storyboard 文件,我們只有先獲取到那個(gè) .storyboard 文件的 Storyboard 實(shí)例,才能獲取其中的控制器;
storyboardWithName:bundle:用來(lái)獲取Storyboard實(shí)例,
instantiateViewControllerWithIdentifier:用來(lái)獲取 其中的某個(gè)控制器;然后就可以使用代碼對(duì)這個(gè)控制器進(jìn)行相應(yīng)的操作,Push/Present/賦值/調(diào)用方法等等;
雖然可以直接在 Storyboard 進(jìn)行 Push/Present 的設(shè)置,但是有時(shí)候也是需要使用代碼來(lái)獲取的;當(dāng)然如果我們?cè)?Storyboard 設(shè)置了轉(zhuǎn)場(chǎng),我們還是可以通過其他的方法來(lái)獲取到下一個(gè)控制器的;下面會(huì)有介紹;
2. UIStoryboardSegue
Segue 的概念對(duì)于一個(gè)初次使用 Storyboard 人來(lái)說(shuō)比較模糊,其實(shí)他就是兩個(gè)控制器之間的轉(zhuǎn)場(chǎng)連線:UIStoryboardSegue 提供了與之相關(guān)的一些操作方法,獲取 Segue、觸發(fā) Segue、獲取與之相關(guān)的控制器等;這個(gè)類也很簡(jiǎn)單,其 API 主要有兩個(gè)初始化方法,三個(gè)屬性和一個(gè)實(shí)例方法:
+ (instancetype)segueWithIdentifier:(nullable NSString *)identifier source:(UIViewController *)source destination:(UIViewController *)destination performHandler:(void (^)(void))performHandler
- (instancetype)initWithIdentifier:(nullable NSString *)identifier source:(UIViewController *)source destination:(UIViewController *)destination
@property (nullable, nonatomic, copy, readonly) NSString *identifier;
// 從那個(gè)控制器過來(lái)的
@property (nonatomic, readonly) __kindof UIViewController *sourceViewController;
// 將要出現(xiàn)的控制器
@property (nonatomic, readonly) __kindof UIViewController *destinationViewController;
// 在自定義UIStoryboardSegue的時(shí)候,可通過重寫這個(gè)方法來(lái)定制一些行為
- (void)perform;
其中,我們常用的是那三個(gè)屬性:identifier、sourceViewController 和 destinationViewController;
最后一個(gè)實(shí)例方法 perform ,就是上面自定義 UIStoryboardSegue 的子類時(shí)必須要實(shí)現(xiàn)的方法;
如下圖所示,即是一個(gè)Segue:

在右側(cè)屬性面板的
Storyboard Segue欄目下:
Identifier:設(shè)置Segue的唯一標(biāo)識(shí)符
Class:設(shè)置Segue的關(guān)聯(lián)類,一般是UIStoryboardSegue的子類,除非需要自定義轉(zhuǎn)場(chǎng),一般不需要設(shè)置
Kind:轉(zhuǎn)場(chǎng)方式,這里選擇的是Push,可以通過該值選擇其他的方式
當(dāng)我們通過 Storyboard 進(jìn)行 Push/Present 的時(shí)候,我們可以通過系統(tǒng)方法獲取一個(gè) UIStoryboardSegue 實(shí)例,再?gòu)闹蝎@取到我們需要的信息;
在我們使用代碼操作 Segue 的時(shí)候,一定要確保待操作的 Segue 是已經(jīng)存在的;Segue 的創(chuàng)建是在 Storyboard 中進(jìn)行連線添加的,他有兩種:第一種是單個(gè)控件跳轉(zhuǎn)某個(gè)控制器的連線,例如按鈕跳轉(zhuǎn)到下一個(gè)控制器,是一對(duì)一的關(guān)系這種我們不需要使用代碼就可以觸發(fā)相應(yīng)的事件,在 Storyboard 中創(chuàng)建就能確定關(guān)系的;還有一種是控制器之間的連線,可能不止一個(gè)連線,跳轉(zhuǎn)到不同控制器,也可能是不同的事件觸發(fā),跳轉(zhuǎn)到同一個(gè)控制器,這種是在 Storyboard 中創(chuàng)建 Segue時(shí),不能確定跳轉(zhuǎn)時(shí)機(jī)與跳轉(zhuǎn)關(guān)系的。
能夠在 Storyboard 中確定跳轉(zhuǎn)關(guān)系
這種在 Storyboard 中就可以確定跳轉(zhuǎn)關(guān)系,例如通過某個(gè)按鈕跳轉(zhuǎn)到下一個(gè)控制器,我們可以這樣連線:

連線方法:選中前一個(gè)控制器或者其中能夠觸發(fā)事件的控件(例如按鈕),然后按住鍵盤 CTRL(Control)鍵,最后按住鼠標(biāo)左鍵,拖到需要跳轉(zhuǎn)的控制器中松手;會(huì)彈出轉(zhuǎn)場(chǎng)的方式(常用Push/Present等),即可!
不能夠在 Storyboard 中確定跳轉(zhuǎn)關(guān)系
上面是通過一個(gè)按鈕的事件來(lái)轉(zhuǎn)場(chǎng)到下一個(gè)場(chǎng)景的連線,按鈕和下一個(gè)轉(zhuǎn)場(chǎng)場(chǎng)景是一對(duì)一的關(guān)系;那如果我們不確定事件觸發(fā)的控件,例如點(diǎn)擊一個(gè)
TableView的cell來(lái)跳轉(zhuǎn)到下一個(gè)控制器,這樣我們是不能在添加控件的時(shí)候就能確定跳轉(zhuǎn)關(guān)系的,像這種一對(duì)多的關(guān)系應(yīng)該怎么來(lái)添加連線呢, 實(shí)現(xiàn)跳轉(zhuǎn)呢?
這里需要兩個(gè)步驟,一是添加控制器之間的跳轉(zhuǎn)關(guān)系,即添加 Segue,然后在想應(yīng)的事件中出發(fā)不同的 Segue,來(lái)實(shí)現(xiàn)不同的跳轉(zhuǎn);第二步使用代碼來(lái)觸發(fā)相應(yīng)的 Segue,實(shí)現(xiàn)跳轉(zhuǎn)事件;
- 添加控制器間的
Segue
選中控制器,注意不是任何控件,而是控制器本身,然后按住鍵盤 CTRL(Control)鍵,同時(shí)按住鼠標(biāo)左鍵,拖到需要跳轉(zhuǎn)的控制器中松手;會(huì)彈出轉(zhuǎn)場(chǎng)的方式(常用Push/Present等),即可!

然后,選中該 Segue,在左側(cè)屬性欄設(shè)置標(biāo)識(shí)符:

這種方式添加的 Segue,不會(huì)自動(dòng)觸發(fā),最后需要我們使用下節(jié)介紹的相關(guān) API來(lái)觸發(fā)該Segue:
[self performSegueWithIdentifier:@"aboutusSegueID" sender:model];
刪除 Segue
刪除一個(gè) Segue很簡(jiǎn)單,選中待刪除的Segue,然后按鍵盤 Delete 鍵即可;
3. UIViewController 相關(guān) API
UIViewController 是我們使用最多的類之一,其中和 Storyboard 相關(guān)的 API,大概有以下這些:
// 當(dāng)前控制器所屬的 Storyboard
@property(nullable, nonatomic, readonly, strong) UIStoryboard *storyboard ;
// 使用代碼來(lái)進(jìn)行 Segue 的跳轉(zhuǎn)
// identifier: Segue 標(biāo)識(shí)符
// sender: 攜帶的參數(shù)
- (void)performSegueWithIdentifier:(NSString *)identifier sender:(nullable id)sender ;
// Segue 初始化的時(shí)候會(huì)調(diào)用,重寫這個(gè)方法,可以決定當(dāng)前 Segue 是否能成功跳轉(zhuǎn)
- (BOOL)shouldPerformSegueWithIdentifier:(NSString *)identifier sender:(nullable id)sender ;
// 將要跳轉(zhuǎn)的時(shí)候調(diào)用,在這里我們可以獲取到將要跳轉(zhuǎn)的控制器,攜帶一些參數(shù)過去
//sender:對(duì)應(yīng)著 performSegueWithIdentifier 中的sender參數(shù)
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(nullable id)sender ;
performSegueWithIdentifier 如果我們的點(diǎn)擊事件沒有連線,可以在點(diǎn)擊方法里,使用這個(gè)方法來(lái)執(zhí)行 Segue 的跳轉(zhuǎn)(連線必須是存在的,但連的不是當(dāng)前點(diǎn)擊的按鈕);
shouldPerformSegueWithIdentifier 方法是在 Segue 初始化的時(shí)候系統(tǒng)自動(dòng)調(diào)用,可以重寫這個(gè)方法,添加一些邏輯判斷,決定當(dāng)前是否可以跳轉(zhuǎn),返回 YES 可以,返回 NO 不可以;
prepareForSegue 即將跳轉(zhuǎn)的時(shí)候調(diào)用,可以重寫這個(gè)方法,通過 segue 參數(shù)獲取下一個(gè)即將跳轉(zhuǎn)的控制器,進(jìn)行一些操作,例如傳遞參數(shù)給下一個(gè)控制器;
- (BOOL)canPerformUnwindSegueAction:(SEL)action fromViewController:(UIViewController *)fromViewController withSender:(id)sender NS_AVAILABLE_IOS(6_0);
// Returns a subset of the receiver's childViewControllers in the order they should be searched for an unwind destination.
// The default implementation first sends itself -childViewControllerContainingSegueSource:, then returns a copy of its childViewControllers array excluding that object. A custom container view controller can override this method to affect the order in which its children are searched, or to modify the result of the default implementation.
// For compatibility, if a view controller overrides the deprecated -viewControllerForUnwindSegueAction:fromViewController:sender: method, but does not override this method, it will receive the deprecated method instead of this method.
// To affect this view controller's eligibility as an unwind destination, override -canPerformUnwindSegueAction:fromViewController:withSender: instead.
- (NSArray<UIViewController *> *)allowedChildViewControllersForUnwindingFromSource:(UIStoryboardUnwindSegueSource *)source NS_AVAILABLE_IOS(9_0);
// Returns the child view controller that contains the provided segue source.
// Custom container view controllers should call this method from their implementation of -allowedChildViewControllersForUnwindingFromSource: to exclude the result from the returned array, as well as to determine the order of the returned array's contents.
// Do not try to re-implement or override this method; it takes special care to handle situations such as unwinding from a modally-presented view controller.
- (nullable UIViewController *)childViewControllerContainingSegueSource:(UIStoryboardUnwindSegueSource *)source NS_AVAILABLE_IOS(9_0);
// Deprecated. Returns a direct child of the receiver that responds YES to -canPerformUnwindSegueAction:fromViewController:withSender:, or self if no children respond YES but the receiver itself does. If this method has been overridden, UIViewController's implementation does not consult child view controllers at all, and skips straight to sending -canPerformUnwindSegueAction:... to self.
// Applications targeting iOS 9 or later should not override this method. Applications can instead override -allowedChildViewControllersForUnwindingFromSource: to guide UIKit’s search for a descendant view controller that returns YES from -canPerformUnwindSegueAction:fromViewController:withSender:.
- (nullable UIViewController *)viewControllerForUnwindSegueAction:(SEL)action fromViewController:(UIViewController *)fromViewController withSender:(nullable id)sender NS_DEPRECATED_IOS(6_0, 9_0);
// Custom container view controllers should override this method to modify themselves as part of an ongoing unwind segue. The subsequentVC is the parent, child, or presented view controller closest to the receiver in the direction of the segue's destinationViewController. For example, UINavigationController's implementation of this method will pop any necessary view controllers to reveal the subsequentVC.
- (void)unwindForSegue:(UIStoryboardSegue *)unwindSegue towardsViewController:(UIViewController *)subsequentVC NS_AVAILABLE_IOS(9_0);
// Deprecated. This method is only used for unwind segues whose destination view controller has been returned by an override of the deprecated method -viewControllerForUnwindSegueAction:fromViewController:withSender:. In that case, UIKit will choose a view controller to act as the “executor” of the unwind. If the destination view controller is being modally presented, the destination view controller itself is the executor. Otherwise, the destination view controller’s parent view controller is the executor. If the executor overrides this method, UIKit will ignore the Custom Class specified in Interface Builder and instead call this method on the executor to obtain a segue that can perform the unwind.
// The returned segue object must be able to perform all steps necessary to unwind, including dismissing any intermediate modal presentations or popping any necessary navigation items.
// Applications targeting iOS 9 or later should not override this method. Custom container view controllers should instead override -unwindForSegue:towardsViewController: to modify their local state as part of a UIKit-generated incremental unwind segue.
- (nullable UIStoryboardSegue *)segueForUnwindingToViewController:(UIViewController *)toViewController fromViewController:(UIViewController *)fromViewController identifier:(nullable NSString *)identifier NS_DEPRECATED_IOS(6_0, 9_0);
以上都是從前往后的轉(zhuǎn)場(chǎng),例如 push/present 操作;當(dāng)然也少不了從后往前的返回操作,例如 pop/dismiss 操作,這就用到了 Unwind Segues 相關(guān)的一些方法,具體可參考 使用Unwind Segues
以上就是在使用 Storyboard 時(shí)能夠使用到的相關(guān)API。