記得前面講過,Storyboard 裡面可以放置多個頁面(ViewController),頁面之間的跳轉關係也可以在storyboard 裡面定義,接下來我們就來介紹如何在 Storyboard 上設計多頁面
使用 Storyboard 時,我們先來對場景(scene)以及 Segues 來做介紹,在 Storyboard 中,一個場景對應一個在畫面上的內容(如一個ViewController),Segue 則是位於兩個場景間,表示從一個場景轉場至另一個場景
以下就讓我們來做一個多頁面的範例:
首先點選在Xcode 右上角的元件庫(+)按鈕來顯示元件庫,搜尋ViewController 並將其拉入 storyboard 裡面
此時我們需要建立一個UIViewController
檔,來給我們新建立的ViewController 連結,像是Storyboard 上預設的 ViewController 便已經預設與建專案時產生的ViewController.swift
連結,方便我們之後能對其畫面做處理
點擊Xcode 上的 File → New → File...
選擇 Cocoa Touch Class 再點 Next
設定類別名字後選擇UIViewController 作為父類別再按 Next
然後在檢查欲建立的路徑後按 Create,就建立ViewController
成功了
最後我們需要把剛建立的SecondViewController.swift
,與之前在 StoryBoard 上建立的ViewController 做連結,讓我們點擊 Main.StoryBoard
,並選取之前建立的ViewController
然後在Xcode 工具區( Utility Area )下點選 Identity Inspector,並在Class 欄位選擇我們剛剛建立的的SecondViewController.swift
就完成連結了
接下來我們可以對SecondViewController.swift
設計UI,並透過之前介紹的 Assistant Editor 直接產生介面元件所需的程式碼
接下來我們要在 Storyboard 建立Segue
,我們對著第一個 ViewController 按下control + 滑鼠左鍵或是滑鼠右鍵後拖曳到SecondViewController(在 Storyboard 上直接進行操作 或 在 Storyboard 項目工作區操作皆可,且可互相操作,如下)
然後在出現的選單裡選擇Show
補充:
Segue
可以由不同的地方做觸發,等專案之後變更複雜時,不同 ViewController 之間的Segue
將不只有一個而已,因此,我們要為Segue
個別加上唯一的識別碼identifier,而這個識別碼在程式中就是與其他的Segue
做區分用的字串之後有需求時,會在不同的 ViewController 使用
Segue
進行資料的傳遞,Segue
管理 ViewController 間的轉場,以及在轉場間所包含的 ViewController。而當Segue
被觸發後,ViewController 轉場發生前,Storyboard 在執行期間會透過呼叫其prepare(for:sender:)
方法來通知此 ViewController,預設的prepare(for:sender:)
方法不會執行任何事,不過我們可以透過覆寫此方法來將原本頁面 ViewController 的資料傳遞至新的頁面 ViewController
接下來如上面補充所說的,我們要幫Segue
設定識別碼,先在 Storyboard 上選取剛剛建立的Segue
(如下圖,可直接點選 ViewController 間的Segue
或是在第一個ViewController 場景裡的Segue
)
然後在工具區( Utility Area )下點選屬性檢閱器( Attributes Inspector ),並在 identifier 欄位為 Segue 設名字
接下來我們將對第一個 ViewController 做跳轉到 SecondViewController 的程式編寫,我們在之前建立的按鈕點擊事件上,新增以下程式碼,讓我們按下按鈕時,會去執行我們剛剛設定的Segue
來跳轉到 SecondViewController 頁
@IBAction func buttonPressed(_ sender: Any) {
self.performSegue(withIdentifier: "showSecondPage", sender: self)
}
接著如果有要傳遞資訊至 SecondViewController 的話,我們先在 SecondViewController 設一個變數去接傳來的值,並讓的SecondViewController 的 Label 文字更換為傳來的字串
class SecondViewController: UIViewController {
@IBOutlet weak var label: UILabel!
var textForLabel = ""
override func viewDidLoad() {
super.viewDidLoad()
label.text = textForLabel
}
}
最後當Segue
被觸發後,第一個 ViewController 轉場發生前,其prepare(for:sender:)
方法將會被呼叫,而我們要透過覆寫此方法來將第一個 ViewController 的資料傳遞至 SecondViewController
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "showSecondPage" {
if let secondViewController = segue.destination as? SecondViewController {
secondViewController.textForLabel = "Hello world"
}
}
}
這樣我們就成功完成頁面間傳遞資料了
至於要如何返回上一頁呢?
我們前面是透過在第一個 ViewController 建立一個Segue
來實現跳轉去 SecondViewController,那麼要返回至第一個 ViewController 的話,我們就要在第一個 ViewController 上解除UnwindSegue
來回到第一個 ViewController
在 SecondViewController 先定義一個要傳回去的值
var dataPassed = "Pass something back"
在第一個 ViewController 下定義 Unwind Segue 要連結的方法 unwindToThisView(segue:)
。
@IBAction func unwindToThisView(sender: UIStoryboardSegue) {
if let sourceViewController = sender.source as? SecondViewController {
// 收到傳回來的值後要做的動作
passedBackLabel.text = sourceViewController.dataPassed
}
}
之後要在 Storyboard 上選取 SecondViewController 來與 Unwind Segue (即剛剛的unwindToThisView
)連結,這邊在 SecondViewController 上透過按鈕來操作(如下圖,連結方式同之前 建立Segue
,進行拖曳,只是改拖曳至 Exit )
然後在跳出來的選擇清單選我們剛剛建立的 Unwind Segue 方法
這樣我們就完成多頁面的設計以及之間的互動了