構建 iOS 界面:子類化 Views

作者: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 OutletsroundedCornerButton 旁邊的 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.layerself 是一個對該實例的引用格侯。這意味著在 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评矩。

最后編輯于
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末叶堆,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子斥杜,更是在濱河造成了極大的恐慌虱颗,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,000評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件蔗喂,死亡現(xiàn)場離奇詭異忘渔,居然都是意外死亡,警方通過查閱死者的電腦和手機缰儿,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,745評論 3 399
  • 文/潘曉璐 我一進店門畦粮,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事宣赔≡铮” “怎么了?”我有些...
    開封第一講書人閱讀 168,561評論 0 360
  • 文/不壞的土叔 我叫張陵儒将,是天一觀的道長吏祸。 經(jīng)常有香客問我,道長钩蚊,這世上最難降的妖魔是什么贡翘? 我笑而不...
    開封第一講書人閱讀 59,782評論 1 298
  • 正文 為了忘掉前任,我火速辦了婚禮两疚,結果婚禮上床估,老公的妹妹穿的比我還像新娘。我一直安慰自己诱渤,他們只是感情好,可當我...
    茶點故事閱讀 68,798評論 6 397
  • 文/花漫 我一把揭開白布谈况。 她就那樣靜靜地躺著勺美,像睡著了一般。 火紅的嫁衣襯著肌膚如雪碑韵。 梳的紋絲不亂的頭發(fā)上赡茸,一...
    開封第一講書人閱讀 52,394評論 1 310
  • 那天,我揣著相機與錄音祝闻,去河邊找鬼占卧。 笑死,一個胖子當著我的面吹牛联喘,可吹牛的內(nèi)容都是我干的华蜒。 我是一名探鬼主播,決...
    沈念sama閱讀 40,952評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼豁遭,長吁一口氣:“原來是場噩夢啊……” “哼叭喜!你這毒婦竟也來了?” 一聲冷哼從身側響起蓖谢,我...
    開封第一講書人閱讀 39,852評論 0 276
  • 序言:老撾萬榮一對情侶失蹤捂蕴,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后闪幽,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體啥辨,經(jīng)...
    沈念sama閱讀 46,409評論 1 318
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,483評論 3 341
  • 正文 我和宋清朗相戀三年盯腌,在試婚紗的時候發(fā)現(xiàn)自己被綠了溉知。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,615評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖着倾,靈堂內(nèi)的尸體忽然破棺而出拾酝,到底是詐尸還是另有隱情,我是刑警寧澤卡者,帶...
    沈念sama閱讀 36,303評論 5 350
  • 正文 年R本政府宣布蒿囤,位于F島的核電站,受9級特大地震影響崇决,放射性物質(zhì)發(fā)生泄漏材诽。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,979評論 3 334
  • 文/蒙蒙 一恒傻、第九天 我趴在偏房一處隱蔽的房頂上張望脸侥。 院中可真熱鬧,春花似錦盈厘、人聲如沸睁枕。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,470評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽外遇。三九已至,卻和暖如春契吉,著一層夾襖步出監(jiān)牢的瞬間跳仿,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,571評論 1 272
  • 我被黑心中介騙來泰國打工捐晶, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留菲语,地道東北人。 一個月前我還...
    沈念sama閱讀 49,041評論 3 377
  • 正文 我出身青樓惑灵,卻偏偏與公主長得像山上,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子泣棋,可洞房花燭夜當晚...
    茶點故事閱讀 45,630評論 2 359

推薦閱讀更多精彩內(nèi)容

  • 9月3日到6日由于開會出差胶哲,在這一段時間內(nèi)有一些感受想法,也許以后自己也會有機會組織會議潭辈。01首先鸯屿,需要整理有多少...
    遇見活在當下的自己閱讀 306評論 0 0
  • Sorry,my English is poor. 學習英語后把敢,我很快掌握了這句話寄摆,潛意識里覺得這可能...
    Clearness閱讀 524評論 0 0