作者:Reda Lemeden,原文鏈接桦他,原文日期:2016-04-28
譯者:wiilen乾吻;校對:bestswifter燃观;定稿:CMB
這篇文章是 構建 iOS 界面 系列的第四篇叽讳,本篇重點介紹:在沒有原生系統(tǒng)編程經(jīng)驗的情況下追他,如何實現(xiàn) iOS 的設計 —— 這對 Web 設計師及開發(fā)者們來說是極好的。這里也提供前面幾篇文章:第一部分 - 第二部分 - 第三部分岛蚤。
在上一篇文章中邑狸,我們交替使用 Interface Builder 和 Swift,實現(xiàn)了一個自定義的按鈕 —— 如果你一遍又一遍重復這個過程涤妒,除非你開發(fā)的是一個手電筒 App单雾,UI 上只有一個按鈕,不然這項工作很快就會讓人心累她紫。即便不談無聊的重復工作硅堆,如果只更新一點功能上的細節(jié),也需要對每一個按鈕的實例進行修改贿讹,這種做法也是不靠譜的渐逃。下面我們將介紹一種更好的方法。
更恰當?shù)姆椒?/h2>
我們之前也提過民褂,通過繼承已有類的方法和屬性茄菊,來創(chuàng)建一個新的類,這個過程被稱為子類化赊堪。子類可以有選擇地重寫父類的行為面殖,如果我們自定義 UIButton
的默認外觀,子類化正是我們需要的方法哭廉。讓我們看看具體應該怎么做脊僚。
如果你之前就下過 Swiftbot 工程項目,可以直接打開遵绰。你也可以從 GitHub 上下載辽幌。
在 project navigator 右鍵點擊父文件夾,選擇 New File... 來添加一個新文件:
選擇 iOS 下的 Source街立,然后從模版中選擇 Cocoa Touch Class舶衬。
把類的命名為 RoundedCornerButton,然后將 Subclass of 那一行設為 UIButton赎离,其他部分不動逛犹。在 Swift 中一般使用駝峰式命名法。為這個類取一個可以描述具體用途的名字梁剔,是一種好習慣虽画。
在剛生成的 Swift 文件中,刪除所有的注釋 —— 那些開頭帶有 //
的代碼荣病。最后代碼看起來應該像下面這樣:
import UIKit
class RoundedCornerButton: UIButton { }
上面這段代碼幾乎是在 Swift 中創(chuàng)建一個子類所需要的最少代碼码撰。第一篇文章中也介紹過,import UIKit
可以讓我們訪問那些定義在 UIKit 中的 API个盆,這個例子中指的是 UIButton
脖岛。
只創(chuàng)建一個子類還不夠朵栖,目前 Interface Builder 依然把我們的按鈕當作 UIButton
。在我們增加代碼之前柴梆,子類還只相當于父類的一個副本陨溅。
類與實例
我們之前提到過,在 Swift 中绍在,每個 control 都由 UIKit 中的某個類來表示门扇。不過那時候我們還沒有說明的是,這些類只定義了 view 對象最基礎的外觀和行為偿渡。換句話說臼寄,我們很少直接使用它們。
這也是實例發(fā)揮作用的地方溜宽。實例指的是遵循給定類的規(guī)范而構建的對象吉拳。在這個例子中,我們在 IB 中添加的按鈕是 RoundedCornerButton
的實例坑质。
請注意 UIButton
類是如何在不具體設定值的情況下合武,聲明每個按鈕都需要有個 buttonType
屬性的。按鈕的實例可以自己決定 buttonType
涡扼。
現(xiàn)在稼跳,將我們的按鈕改為這個新的子類的實例。
在 storyboard 中吃沪,選中這個按鈕汤善,點擊右側工具欄中的第三個(ID)圖標。這會切換到 Identity inspector票彪,你可以在這里修改這個按鈕實例獨有的屬性红淡,比如它的類和 identifier。
在 Class 選項框中降铸,輸入之前創(chuàng)建的子類的名字在旱。這會將這個按鈕修改為 RoundedCornerButton
的實例,這樣我們之前用代碼創(chuàng)建的自定義行為推掸,就都能應用到這個按鈕上了桶蝎。
對子類的處理先到這里,由于現(xiàn)在我們不需要從 view controller 中直接訪問這個按鈕實例谅畅,讓我們先把之前創(chuàng)建的 outlet connection 移除登渣。有幾種方式可以做到這點,最簡單的方法是:點擊右側面板最后一個圖標毡泻,切換到 Connections inspector胜茧,點擊 Referencing Outlets 下 roundedCornerButton
旁邊的 x 。
刪除了 outlet 之后仇味,我們需要移除 ViewController.swift
中對這個按鈕的所有引用呻顽。刪除該類聲明部分的所有代碼雹顺,最后代碼看起來應該是下面這樣:
class ViewController: UIViewController { }
我們接下來沒有什么需要用到 Interface Builder 的地方了。在我們回去繼續(xù)處理子類之前芬位,我們會給你一些啟發(fā)无拗,幫助你了解如何使用子類化來擴展 UIKit controls。
子類化的常用策略
當我們使用子類化時昧碉,最常見的任務 —— 同時也常是最有挑戰(zhàn)性的任務 —— 是弄清楚哪些方法和屬性需要重寫,以及執(zhí)行你自己添加的代碼的順序揽惹。如果什么地方出錯了被饿,一般是因為你對錯誤的方法進行了重寫,或是代碼執(zhí)行順序出了差錯搪搏。
對 UIView 的子類來說狭握,你常常想讓 view 在加載完后立即應用自定義的樣式。一般我們對下面這些方法進行重寫:
-
awakeFromNib()
疯溺,在 view 從 IB 中加載時被調(diào)用论颅。 -
drawRect(_:)
,在 view 需要將自己繪制到屏幕上時被調(diào)用囱嫩。 -
layoutSubviews()
恃疯,在 view 需要確定 subview 的大小與位置時被調(diào)用。
當然還有更多其他方法墨闲,這篇文章中無法一一介紹今妄。如果感到好奇,你可以通過閱讀官方的 UIView 文檔來了解細節(jié)鸳碧。
重寫
為了在 Swift 中重寫一個方法盾鳞,我們在方法的開頭添加 override
關鍵字,就像下面這樣:
class RoundedCornerButton: UIButton {
override func awakeFromNib() { }
}
我們重寫了 awakeFromNib()
方法瞻离,在這個方法中加入我們的對圖層的自定義腾仅,看上去這是一個不錯的選擇。如果你在做出這些改動之后運行你的 App套利,你會發(fā)現(xiàn)四個角依然是直角推励。這不出所料,因為我們移除了那些在 view controller 中設置實例圖層的 cornerRadius
的代碼日裙。
在之前的代碼中吹艇,為了設置圓角,我們是這樣做的:
roundedCornerButton.layer.cornerRadius = 4
由于現(xiàn)在我們直接在按鈕的子類中進行修改昂拂,我們不需要再引用 roundedCornerButton
:
class RoundedCornerButton: UIButton {
override func awakeFromNib() {
layer.cornerRadius = 4
}
}
在這個例子中受神,layer
等同于 self.layer
,self
是一個對該實例的引用格侯。這意味著在 Swift 中你很少需要寫 self
鼻听,除非編譯器建議你這么做财著。
再次運行你的 App,現(xiàn)在我們的按鈕上應該已經(jīng)應用了圓角效果撑碴。
接下來的部分比較有趣:如果你在 IB 中按住 alt 來拖動并復制按鈕撑教,新的按鈕會與原來的按鈕完全相同,你不需要在 view controller 中改動新按鈕的屬性來達到這個效果醉拓。
不過這里也有個小問題伟姐。目前我們在 IB 中設置了按鈕的背景顏色。這意味著如果以后需要修改所有按鈕的顏色亿卤,我們需要在 IB 中手動修改每個按鈕愤兵。
這個問題容易解決。我們只需要在子類中直接修改 roundedCornerButton
的背景顏色屬性排吴,這樣所有的按鈕的背景顏色都會被改為同一顏色:
class RoundedCornerButton: UIButton {
override func awakeFromNib() {
layer.cornerRadius = 4
backgroundColor = UIColor(red: 0.75, green: 0.20, blue: 0.19, alpha: 1.0)
}
}
如果你運行 App秆乳,你會發(fā)現(xiàn)兩個按鈕的顏色都變成了 Tall Poppy 色 —— 一種由 Kromatic 命名的顏色。上面說的方法也可以用于修改字體钻哩、字體顏色屹堰,甚至可以用于添加新的行為,比如展示某種進行中的狀態(tài)街氢。
結語
子類化是一種構建自定義 iOS 界面的強大工具扯键。你也可以不使用它,但如果你需要構建一個健全的阳仔、可擴展的忧陪、模塊化的系統(tǒng),它會為你提供許多幫助近范。
本文由 SwiftGG 翻譯組翻譯嘶摊,已經(jīng)獲得作者翻譯授權,最新文章請訪問 http://swift.gg评矩。