讀古今文學網 > iOS編程基礎:Swift、Xcode和Cocoa入門指南 > 7.4 nib實例的其他配置 >

7.4 nib實例的其他配置

當nib加載完畢後,其實例已經是功能完備的了;它們已經通過屬性與尺寸查看器中的所有屬性初始化和配置好了,其插座變量用於設置相應實例變量的值。然而,當對像從加載的nib中實例化後,你可能還想向初始化過程附加自己的代碼。本節將會介紹幾種做法。

一種常見的情況是視圖控制器(當包含主視圖的nib加載時,它作為擁有者,因此在nib中表示為nib擁有者對像)擁有一個插座變量,它指向從nib實例化的界面對象。在這種架構中,視圖控制器可以對該界面對像做進一步的配置,因為nib加載後它有一個指向它的引用——相應的實例屬性。進行這種配置最方便的地方就是其viewDidLoad方法。在調用viewDidLoad時,視圖控制器的視圖已經加載了,也就是說,視圖控制器的view屬性已經設為了實際的主視圖,這是從nib實例化的,所有插座變量都會連接起來;不過視圖尚未出現在可視化界面上。

另一種可能是除了在nib中進行配置,你還希望nib對像能夠自我配置。通常來說,這是因為你有一個內建界面對像類的自定義子類。事實上,你想要創建自定義類,從而放置一些自定義代碼。你要解決的問題是nib編輯器不允許你進行後續配置,或有很多對象,並且希望以一種一致且精心設定好的方式進行配置,這樣相對於單獨配置每一個,通過共同類進行配置才更有意義。

一種方式是在自定義類中實現awakeFromNib。對像通過nib加載實例化後(對像初始化並配置完畢,其連接也建立起來了),awakeFromNib會向所有這些對像發送消息。

比如,下面創建一個按鈕,無論在nib中如何配置,其背景色總是紅色的(這個例子沒什麼意義,不過能說明問題)。在Empty Window項目中,創建一個按鈕子類RedButton:

1.在項目導航器中,選擇File→New→File。然後選擇iOS→Source→Cocoa Touch Class,單擊Next按鈕。

2.將新建的類命名為RedButton,讓它成為UIButton的子類,單擊Next按鈕。

3.確保將其保存到項目目錄中,位於Empty Window分組下,同時勾選Empty Window應用目標,單擊Create按鈕。Xcode會創建RedButton.swift。

4.在RedButton.swift的RedButton類的聲明中,實現awakeFromNib:


override func awakeFromNib {
    super.awakeFromNib
    self.backgroundColor = UIColor.redColor
}
  

現在有一個UIButton子類,在其從nib實例化時,它會變成紅色。不過,任何nib中都沒有該子類的實例。編輯故事板,選中已經位於主視圖中的按鈕,使用身份查看器將按鈕所屬的類改為RedButton。

構建並運行項目。當然,按鈕現在是紅色的!

還可以使用nib對像身份查看器中的User Defined Runtime Attributes。可以通過它配置nib編輯器中沒有內建界面的nib對象的方方面面。這裡實際做的是在nib加載時發送nib對象,一個setValue:forKeyPath:消息,鍵路徑會在第10章介紹。自然而然地,對像需要做一些準備來響應給定的鍵路徑,否則nib加載時應用會崩潰。

比如,nib編輯器的一個缺點是它無法配置層屬性。假設我們要通過nib編輯器將紅色按鈕改為圓角的。在代碼中,要通過設置按鈕的layer.cornerRadius屬性實現上述目標。nib編輯器無法訪問該屬性。相反,可以在nib編輯器中選中按鈕,使用身份查看器中的User Defined Runtime Attributes。將Key Path設為layer.cornerRadius,將Type為Number,將Value值設置成什麼都可以,如10(如圖7-17所示)。現在構建並運行;當然,按鈕現在變成圓角的了。

還可以通過將屬性設為可檢查的來配置nib對象的自定義屬性。為了做到這一點,請將@IBInspectable特性添加到屬性聲明中。這樣,屬性就會列在nib對象的屬性查看器中。比如,現在準備在nib編輯器中配置按鈕的邊框。在RedButton類聲明體的開頭添加如下代碼:


@IBInspectable var borderWidth : CGFloat {
    get {
        return self.layer.borderWidth
    }
    set {
        self.layer.borderWidth = newValue
    }
}
  

圖7-17:通過運行時特性將按鈕修改為圓角

上述代碼聲明了一個RedButton屬性borderWidth,並使其成為層的borderWidth屬性前的一個門面。這樣,如果一個按鈕是RedButton類的實例,那麼nib編輯器還會在屬性查看器中顯示出該屬性(如圖7-18所示)。結果就是,當在nib編輯器中為該屬性賦值時,這個值會在nib加載時發送給該屬性的setter,按鈕邊框就會變成值所指定的寬度。

圖7-18:nib編輯器中可檢查的屬性

要想更早地介入對象的初始化過程中,如果對象是個UIView(或是UIView的子類),那麼可以實現init(coder):。值得注意的是,對於UIView,nib加載實例化時並不會調用init(frame:),而會調用init(coder:)。(實現init(frame:),然後想知道當視圖從nib實例化時為何代碼不會被調用是初學者常犯的一個錯誤)。其最簡單的實現如以下代碼所示:


required init?(coder aDecoder: NSCoder) {
    super.init(coder:aDecoder)
    // your code here
}