從 storyboard 的 controller 載入 xib 畫面
storyboard 和 xib 有很多共通點,都可以在 Interface Builder 製作畫面,但是如果想讓 storyboard 的 controller 載入 xib 畫面,讓 controller 同時享有 storyboard 拉 segue 和 xib 畫面重覆利用的好處,有可能嗎 ?
當然有呀 ! 接下來,就讓我們實際創作一個情歌 App 示範吧。
1 在 storyboard 設計 App 畫面
我們想要實現以下兩點功能:
- 在 storyboard 拉出開心的歌和傷心的歌 controller ,因此可以用 segue 串接畫面。
- 開心的歌和傷心的歌將從 xib 載入畫面,因此畫面可以重覆利用。到時候 UI 調整時,只需修改 xib。
2 建立新的 controller SongViewController。
記得勾選 Also create XIB file,如此才會同時建立 xib 檔。
仔細觀察 xib 的 File’s Owner。
(1) 點選 File’s Owner 後,從 Identify Inspector 頁面,可看到它的 Class 被設為 SongViewController。
(2) 選 File’s Owner 後,按右鍵可發現 controller 的 view 連到 xib 的 View 元件。
從以上兩點,我們了解到時候搭配 xib 檔的 controller 物件生成後,畫面將為 xib 裡的 View 元件,而且 controller 的型別為 SongViewController(或是繼承 SongViewController 的類別)。
3 在 SongViewController.xib 裡加上顯示歌名的 label。
4 拉 outlet collection songLabels,方便到時候從程式設定歌名。
5 建立繼承 SongViewController 的 HappySongViewController & SadSongViewController
6 設定開心的歌和傷心的歌
開心的歌
class HappySongViewController: SongViewController {override func viewDidLoad() { super.viewDidLoad() songLabels[0].text = "有點甜" songLabels[1].text = "愛的主旋律" songLabels[2].text = "戀愛頻率"}
傷心的歌
class SadSongViewController: SongViewController { override func viewDidLoad() { super.viewDidLoad() songLabels[0].text = "街角的祝福" songLabels[1].text = "小幸運" songLabels[2].text = "怎樣"}
7 將開心的歌設為 HappySongViewController,傷心的歌設為 SadSongViewController。
7 在 SongViewController 裡覆寫 loadView,利用 loadNibNamed(_:owner:options:) 載入 SongViewController.xib 的畫面。
class SongViewController: UIViewController { @IBOutlet var songLabels: [UILabel]! override func loadView() { super.loadView() Bundle.main.loadNibNamed("SongViewController", owner: self, options: nil)}
在 SongViewController.xib 裡,File’s Owner 的類別是 SongViewController,它代表 SongViewController 或繼承 SongViewController 的類別建立的物件都可以當 File’s Owner。
當 App 顯示開心的歌時,controller 的型別為 HappySongViewController。當 loadView 執行,呼叫 loadNibNamed(_:owner:options:) 時,傳入當 owner 的 self 型別正是 HappySongViewController。此時它會把 controller 的 view 換成 xib 的 view,取代原本 storyboard 裡的 view。至於傷心的歌,也是類似的道理,到時候 owner 的型別將為 SadSongViewController。
最後,為了避免打錯字,xib 的名字也可以用 String(describing: SongViewController.self) 生成,以自動完成的方式輸入。
Bundle.main.loadNibNamed(String(describing: SongViewController.self), owner: self, options: nil)
結果