我們在開發 iOS App 的時候,對於 User interface 的開發模式有幾種流派
- Storyboard
- Storyboard + xib
- xib
- Code
而這篇的主題,先撇除純 Code 流的開發方式,來聊聊使用 Storyboard 和 xib 的朋友,會遇到什麼事。
先說說為什麼我使用 User interface(Storyboard, xib)
一方面是因為一開始學習的時候,教學是從拉拉元件,連動按鈕開始, 比起純 Code 的寫法,這樣也讓人比較好上手; 再來便開始弄一些 Auto layout,讓畫面越來越完整。 而其中一點是,方便和設計師做討論, 看著畫面來調整 UI 會比我一直重新 Build 出 App 還快得一些。 但也正是為了讓設計師可以看到畫面,我可能得在一些 UIKit 的元件上先放置好預設的值, 好比說:
儘管這個 UIViewController 在 viewDidLoad 的時候,會再配置一次多語系的文案以及更換些 icon 或者顏色, 但至少在初步上可以看到大概會長什麼樣子。
若不清空預設值呢?
我們就可能在部分畫面上會看到,原本打在 xib 的 UITextField 上的值(e.g Hinet CHT Auto), 甚至是可能有些元件的 isHidden 是由程式判斷出需不需要呈現, 而畫面顯示到判斷完畢的中間,會造成畫面上元件閃現的情況。 於是原先我的做法會:
- 清空 xib 上的所有預設值
- 在 viewDidLoad 的狀態,執行清空的動作
前者的做法,會影響到的就是 xib 失去了給設計師觀看的意義, 因為全空的畫面並不符合使用者的情境; 而後者的做法,當元件一多的時候,有時便會有疏忽。
class ViewController: UIViewController {
@IBOutlet private weak var nameTextField: UITextField!
@IBOutlet private weak var passwordTextField: UITextField!
@IBOutlet private weak var addressTextField: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
setUpView()
}
private func setUpView() {
nameTextField.placeholder = "給值"
passwordTextField.placeholder = "給值"
addressTextField.placeholder = "給值"
}
}
如上圖,我會在 setUpView() 的時候對 UIKit 元件一一設置。 後來,某天看到了另一種方式處理這一塊:
class ViewController: UIViewController {
@IBOutlet private weak var nameTextField: UITextField! {
didSet {
nameTextField.placeholder = "給值"
}
}
@IBOutlet private weak var passwordTextField: UITextField! {
didSet {
passwordTextField.placeholder = "給值"
}
}
@IBOutlet private weak var addressTextField: UITextField! {
didSet {
addressTextField.placeholder = "給值"
}
}
}
也就是將元件建構的動作寫在 UIKit 的元件 didSet 的時候,對於每個元件該做哪些事情就會有比較清楚的說明。