寫(xiě)在前面
這是我學(xué)習(xí)Swift3.0的學(xué)習(xí)筆記系列的第二篇文章扔罪,本篇同第一篇一樣始腾,將主要介紹Swift的一些基礎(chǔ)語(yǔ)法,包括控制流呕寝、閉包等內(nèi)容勋眯。由于本人水平有限,接觸Swift語(yǔ)言的時(shí)間也只有一個(gè)月左右下梢,所以文中有些描述的不準(zhǔn)確客蹋,甚至是錯(cuò)誤的觀點(diǎn),還望各路大神能夠不吝賜教孽江,幫我指出讶坯。我原來(lái)一直使用Objective-C語(yǔ)言進(jìn)行iOS的開(kāi)發(fā),出于對(duì)新知識(shí)的好奇與渴望岗屏,才開(kāi)始自學(xué)Swift闽巩,但剛開(kāi)始的時(shí)候钧舌,遇到了很多問(wèn)題,網(wǎng)上檢索資料涎跨,發(fā)現(xiàn)目前Swift3.0的學(xué)習(xí)資料比較少洼冻,大部分都是之前版本的,由于3.0較之前版本在某些部分的改動(dòng)還較大隅很,感覺(jué)缺少資料的學(xué)習(xí)還是比較吃力的撞牢,如果你也像我一樣,是剛從OC轉(zhuǎn)向Swift的叔营,并且一開(kāi)始就接觸的是Swift3.0屋彪,那么我的學(xué)習(xí)筆記也許會(huì)對(duì)你有些許幫助。另外绒尊,我有個(gè)和大家一起討論Swift3.0學(xué)習(xí)的技術(shù)交流群185826825畜挥,歡迎大家來(lái)與我們共同學(xué)習(xí)!我的本系列其它文章:
Swift3.0學(xué)習(xí)筆記(一)
-
控制流
-
if else
眾所周知婴谱,Swift沒(méi)有了麻煩的;
作為句尾結(jié)束符蟹但,那么對(duì)于簡(jiǎn)單的條件判斷我們干脆也就不用()
了,現(xiàn)在谭羔,你可以像這樣寫(xiě)一個(gè)if else
:
let a = 3, b = 2
if a > b {
print("a>b的條件為真")
} else {
print("a>b的條件為假")
}
如果是比較復(fù)雜的條件华糖,你仍需要加上()
,來(lái)說(shuō)明條件都包括什么:
let a = 3, b = 2, c = 4, d = 1
let condition_1 = a > b
let condition_2 = c < d
if (condition_1 || condition_2) {
print("條件1為真或者條件2為真")
}
我們?cè)陂_(kāi)發(fā)中瘟裸,經(jīng)常會(huì)判斷一個(gè)對(duì)象是否為nil客叉,在Swift中我們可以這樣做:
let image: UIImage? = UIImage.init(named: "abc")
if let image = image {
print("我們拿到image的內(nèi)容了")
} else {
print("我們拿到的image為nil")
}
此時(shí)如果運(yùn)行后,在MainBundle中沒(méi)有abc.png這個(gè)文件的話话告,控制臺(tái)則會(huì)輸出我們拿到的image為nil
兼搏。在條件判斷時(shí),我們使用了Swift中的if let
語(yǔ)法沙郭,它的含義是佛呻,我們重新定義一個(gè)常量,使用一個(gè)可選類型的值給這個(gè)常量進(jìn)行賦值棠绘,如果賦值后件相,這個(gè)可選類型的值是nil的話再扭,也就相當(dāng)于我們?cè)谑褂?code>if image == nil去進(jìn)行判斷氧苍,需要注意的是,新定義的這個(gè)image
只能在if
的{}
內(nèi)訪問(wèn)泛范。
-
guard else
同剛才那個(gè)案例一樣让虐,我們經(jīng)常會(huì)做一些對(duì)象是否為nil的判斷,事實(shí)上罢荡,我們只會(huì)在對(duì)象不為nil的時(shí)候才會(huì)去做一些邏輯赡突,而當(dāng)對(duì)象真的是nil的時(shí)候对扶,我們也許什么也不做,如果能夠?qū)ξ覀儾黄谕慕Y(jié)果早做檢查惭缰,會(huì)使我們的代碼更加貼近我們想要實(shí)現(xiàn)的目的浪南,并且讓它看起來(lái)更容易理解。guard else
就是來(lái)做這件事的漱受,從字面的意思來(lái)看络凿,保證,除此之外
確實(shí)很容易理解昂羡,那么就讓我們看看這個(gè)語(yǔ)法該怎么使用吧絮记,比如我有一個(gè)用于接收消息的函數(shù),需求是只對(duì)消息內(nèi)容中含有'abc'的內(nèi)容作處理虐先,代碼如下:
func didReceivedMessage(msg: String) {
guard msg.contains("abc") else { return }
print("消息中包含字符串a(chǎn)bc怨愤,我需要做處理了")
}
這里需要注意,在else中一定需要加上return
蛹批,如果是在循環(huán)內(nèi)或switch中可以加break
撰洗,用以結(jié)束這個(gè)函數(shù),不加的話編譯不能通過(guò)般眉。
同if let
語(yǔ)法類似的了赵,guard else
也有guard let else
的用法。
-
switch
和OC的switch相比甸赃,swift的switch語(yǔ)句強(qiáng)大了很多柿汛,用法也更靈活。首先埠对,switch不再只能檢查整型類型的值络断,它還能檢查浮點(diǎn)型、布爾類型项玛、字符串貌笨、元組等,同時(shí)襟沮,每個(gè)case
默認(rèn)都會(huì)有一個(gè)break
锥惋,因此你不再額外需要寫(xiě)break
關(guān)鍵字了;每個(gè)case
下的代碼塊也不需要{}
來(lái)進(jìn)行整理开伏,只需要將代碼寫(xiě)在兩個(gè)case
之間就好膀跌;每個(gè)switch語(yǔ)句必須涵蓋所有的條件,不能夠像OC那樣只寫(xiě)一兩個(gè)你關(guān)注的條件固灵,剩余你不想關(guān)注的條件可以使用default: break
來(lái)補(bǔ)充捅伤;default
關(guān)鍵字不能出現(xiàn)在case的前面。
switch中還增加了一個(gè)有意思的用法巫玻,值綁定丛忆。所謂值綁定就是你可以在case分?里將匹配的值綁定到?個(gè)臨時(shí)的常量或變量祠汇,這個(gè)常量或變量在該case分??就可以被引?了:
switch "abc123" {
case let x where x.hasSuffix("123"):
print("x = \(x)")
default: break
}
控制臺(tái)輸出abc123
,代碼中的let x
就是將匹配到的值賦值給常量x熄诡,where
就是對(duì)被匹配的對(duì)象進(jìn)行篩選可很,使得滿足條件的被匹配對(duì)象才能進(jìn)入case。
switch用來(lái)匹配元組凰浮,就像這樣:
let point = (2, 0)
switch point {
case (let x, 0):
print("點(diǎn)在x軸上根穷,橫坐標(biāo)為\(x)")
case (0, let y):
print("點(diǎn)在y軸上,縱坐標(biāo)為 \(y)")
case let (x, y): //匹配所有
print("點(diǎn)不在坐標(biāo)軸上导坟,該點(diǎn)坐標(biāo)是(\(x), \(y))")
}
-
循環(huán)
循環(huán)語(yǔ)句和OC的循環(huán)類似屿良,大概有for
循環(huán)和while
循環(huán)幾種,對(duì)于for
循環(huán)來(lái)說(shuō)惫周,swift取消了C語(yǔ)言風(fēng)格的for (int i = 0; i < 10; i++)
語(yǔ)法尘惧,取而代之的是這樣for i in 0..<10
,如果你不需要i作為循環(huán)次數(shù)的索引递递,你可以這樣寫(xiě)for _ in 0..<10
喷橙,使用一個(gè)下劃線_
來(lái)省略。你也可以使用for in
對(duì)某個(gè)數(shù)組進(jìn)行遍歷登舞,像這樣:
let arr = Array.init(repeating: "abc", count: 3)
for str in arr {
print(str)
}
控制臺(tái)輸出:
abc
abc
abc
-
數(shù)組
在Swift中贰逾,取消了NS
的前綴,我們可以直接定義一個(gè)Array類型的變量或常量菠秒,但前提是我必須指定存放在數(shù)組中元素的類型疙剑,對(duì)于未知的類型我們可以使用Any來(lái)表示,像這樣:
let array: Array<Any> = [("" as Any)]
我們聲明了一個(gè)不可變數(shù)組践叠,其中有一個(gè)元素言缤,是一個(gè)空字符串,由于類型安全禁灼,我們需要將這個(gè)字符串類型的元素轉(zhuǎn)換為Any
類型管挟。
如果改為var
類型,則該數(shù)組為可變數(shù)組弄捕,可以使用添加僻孝、刪除等函數(shù)對(duì)該數(shù)組進(jìn)行修改:
var array: Array<String> = [""]
array.append("abc")
array.remove(at: 0)
-
字典
同數(shù)組一樣,聲明時(shí)需要指定字典的key-value
的數(shù)據(jù)類型守谓,比如:
var dict = Dictionary<String, Int>()
dict["abc"] = 123
-
類
在Swift中穿铆,沒(méi)有了.h
和.m
文件,取而代之的是一個(gè).swift
文件分飞,在.swift
文件中使用public
和private
關(guān)鍵字來(lái)區(qū)別函數(shù)和屬性的公開(kāi)和私有悴务,對(duì)于沒(méi)有添加這個(gè)關(guān)鍵字的函數(shù)和屬性睹限,在swift中默認(rèn)是公開(kāi)的譬猫。對(duì)于繼承讯檐,swift仍延續(xù)了使用:
來(lái)表示繼承關(guān)系,而之后染服,我們可以方便地使用","
對(duì)要繼承的父類進(jìn)行分割别洪,在后面添加上我們要遵守的協(xié)議,這看起來(lái)就像這樣:
-
懶加載
我們?cè)趕wift中可以在聲明屬性的時(shí)候柳刮,用懶加載的方式進(jìn)行聲明挖垛,這樣類似OC,可以在只有訪問(wèn)這個(gè)屬性的時(shí)候才在內(nèi)存開(kāi)辟空間秉颗。比如這樣:
lazy private var placeHolderLabel: UILabel = {
let tempLabel = UILabel()
return tempLabel
}()
-
屬性監(jiān)聽(tīng)
我們可以使用Swift提供給我們的屬性觀察器痢毒,獲取到屬性被賦值前和被賦值后的時(shí)機(jī),像這樣:
private var x: Int = 0 {
willSet {
print("當(dāng)前值 = \(x)")
print("將被賦予的新值 = \(newValue)")
}
didSet {
print("當(dāng)前值 = \(x)")
print("被賦新值之前的舊值 = \(oldValue)")
}
}
其中在willSet
方法中提供了一個(gè)值newValue
蚕甥,用來(lái)訪問(wèn)這個(gè)屬性要被賦的新值哪替,在didSet
方法中提供了一個(gè)oldValue
用來(lái)訪問(wèn)被賦值之前的舊值,這這兩個(gè)方法中我們都可以使用屬性本身來(lái)訪問(wèn)當(dāng)前的值」交常現(xiàn)在我們讓x = 1
凭舶,可以看到控制臺(tái)輸出:
當(dāng)前值 = 0
將被賦予的新值 = 1
當(dāng)前值 = 1
被賦新值之前的舊值 = 0
-
函數(shù)
swift中,函數(shù)使用關(guān)鍵字func
作為函數(shù)的開(kāi)始爱沟,緊接著后面是函數(shù)名帅霜,不同于OC的風(fēng)格,swift不再將函數(shù)名和參數(shù)混在一起寫(xiě)呼伸,而是將所有的參數(shù)都使用()
括起來(lái)身冀,之后使用一個(gè)->
符號(hào)來(lái)表示此函數(shù)的返回類型,在這個(gè)符號(hào)的后面寫(xiě)上返回類型括享,就像這樣:
func login(userName: String, password: String) -> Bool {
if (userName == "abc" && password == "123") {
return true
}
return false
}
我們都知道在OC中有類方法和實(shí)例方法的區(qū)別闽铐,在Swift中,如果在func
關(guān)鍵字前增加class
關(guān)鍵字奶浦,則該方法為類方法兄墅,否則默認(rèn)都是實(shí)例方法“牟妫可以看到隙咸,剛才我們寫(xiě)的那個(gè)login
的函數(shù)就是一個(gè)實(shí)例方法,我們調(diào)用這個(gè)函數(shù)的方式同OC一樣成洗,首先要有這個(gè)函數(shù)所在類的實(shí)例五督,然后使用實(shí)例對(duì)象去調(diào)用這個(gè)方法,在Swift中瓶殃,不再像OC一樣使用方括號(hào)+空格
的方式去向?qū)ο蟀l(fā)消息充包,而是直接使用點(diǎn)語(yǔ)法
,假設(shè)這個(gè)函數(shù)在某個(gè)類中,我們這樣調(diào)用該函數(shù):
let isSuccess = self.login(userName: "abc", password: "123")
在這個(gè)函數(shù)中基矮,userName
和password
是函數(shù)的形參
淆储,是函數(shù)的內(nèi)部參數(shù)名
,那么對(duì)應(yīng)的家浇,什么是函數(shù)的實(shí)參
和外部參數(shù)名
呢本砰?我們?cè)谡{(diào)用這個(gè)函數(shù)時(shí),在輸入?yún)?shù)的地方钢悲,我們輸入的參數(shù)就是這個(gè)函數(shù)的實(shí)參
点额,對(duì)于外部參數(shù)名
即是指我們?cè)诤瘮?shù)調(diào)用時(shí)所看到的參數(shù)名,其寫(xiě)法是在內(nèi)部參數(shù)名
的前面使用一個(gè)空格
來(lái)分割莺琳,并在前面寫(xiě)上參數(shù)名还棱,比如func inputUserName(用戶名 userName: String) -> Void
,這樣我們?cè)谡{(diào)用這個(gè)函數(shù)時(shí)就是這個(gè)樣子的:
self.inputUserName(用戶名: "abc")
如果我們沒(méi)有刻意去寫(xiě)外部參數(shù)名
惭等,那么在調(diào)用函數(shù)時(shí)會(huì)默認(rèn)該函數(shù)的外部參數(shù)名
同內(nèi)部參數(shù)名
一致诱贿,那么如果我們不希望在調(diào)用時(shí)看到這個(gè)函數(shù)的外部參數(shù)名
該怎么辦呢?像剛才那個(gè)登錄的函數(shù)咕缎,我們可以使用這樣的方式對(duì)外部參數(shù)名進(jìn)行省略:
//注意:函數(shù)的返回值如果是空的話珠十,可以寫(xiě)(),或者Void
//或者直接省略這些: "-> ()"凭豪,即參數(shù)后面直接接函數(shù)體
func login(_ userName: String, _ password: String) -> () {
if (userName == "abc" && password == "123") {
return true
}
return false
}
//函數(shù)調(diào)用
self.login("abc", "123")
另外焙蹭,我們還可以給函數(shù)的參數(shù)一個(gè)默認(rèn)值,比如:
func showMsg(msg: String? = "hello") {
print(msg)
}
self.showMessage()
控制臺(tái)輸出Optional("hello")
-
閉包
閉包其實(shí)類似OC中的Block嫂伞,是一段代碼塊孔厉,可以像函數(shù)一樣實(shí)現(xiàn)某些功能,也可以作為參數(shù)進(jìn)行傳遞帖努,可以看成是匿名函數(shù)撰豺。
閉包的語(yǔ)法:
{(參數(shù)名) -> 返回類型 in
代碼塊
}
//對(duì)比OC的寫(xiě)法
返回類型(^bolck名)(參數(shù)類型及參數(shù)名) {
代碼塊
}
在網(wǎng)上關(guān)于Swift的閉包有比較多的介紹,在此向大家推薦一個(gè)網(wǎng)址來(lái)學(xué)習(xí):Swift教程-閉包
在此舉一個(gè)簡(jiǎn)單的例子拼余,簡(jiǎn)單封裝一下網(wǎng)絡(luò)請(qǐng)求方式:
class func get(url: String, parameters: Dictionary<String, AnyObject>? = nil,
completionHandler: @escaping (_ response: DataResponse<Data>) -> ()) {
Alamofire.request(url, method: .get, parameters: parameters, encoding: URLEncoding.default, headers: nil)
.responseData { (response) in
completionHandler(response)
}
}
細(xì)心的你會(huì)發(fā)現(xiàn)在completionHandler
這個(gè)閉包中有個(gè)@escaping
關(guān)鍵字污桦,字面意思是逃逸,那么什么是逃逸呢匙监?又是否有與之對(duì)應(yīng)的類似不可逃逸的關(guān)鍵字呢凡橱?
-
逃逸閉包
當(dāng)我們?cè)谶M(jìn)行網(wǎng)絡(luò)請(qǐng)求時(shí),由于是異步操作亭姥,所以在函數(shù)返回時(shí)稼钩,閉包中的內(nèi)容可能還沒(méi)有被觸發(fā),所以要求閉包的生命周期能夠長(zhǎng)于函數(shù)本身达罗,也就是讓閉包能夠逃出函數(shù)存在坝撑,這就是逃逸閉包,在函數(shù)聲明時(shí),在閉包前使用@escaping
關(guān)鍵字巡李。
-
非逃逸閉包
對(duì)于某些函數(shù)抚笔,例如Swift數(shù)組中的map函數(shù),其作用是將給定數(shù)組復(fù)制出來(lái)一份副本击儡,并根據(jù)你寫(xiě)的map規(guī)則將此副本映射成一個(gè)新的數(shù)組,對(duì)于這樣執(zhí)行同步操作的函數(shù)蝠引,在函數(shù)執(zhí)行完成之后阳谍,就不再需要此閉包繼續(xù)存在了,可以使用非逃逸閉包
螃概,其關(guān)鍵字是@noescape
矫夯。
let arr = ["a", "b"]
let newArr = arr.map { (originalValue) -> String in
return "字母" + originalValue
}
print(newArr)
控制臺(tái)輸出["字母a", "字母b"]
。
-
參數(shù)名縮寫(xiě)
Swift為閉包提供了參數(shù)名的縮寫(xiě)功能吊洼,我們可以直接使用$0, $1, $2
來(lái)順序訪問(wèn)閉包內(nèi)的參數(shù)训貌,上面那個(gè)例子我們就可以簡(jiǎn)寫(xiě)成這樣:
let arr = ["a", "b"]
let newArr = arr.map({ "字母" + $0 })
-
構(gòu)造器
所謂構(gòu)造器,就是我們可以通過(guò)這個(gè)構(gòu)造器來(lái)構(gòu)造一個(gè)類的實(shí)例冒窍。在OC中递沪,我們使用init
函數(shù)來(lái)對(duì)類進(jìn)行實(shí)例化操作,在Swift中综液,我們有兩種構(gòu)造方式款慨,指定構(gòu)造器和遍歷構(gòu)造器。關(guān)于構(gòu)造器的介紹谬莹,我引用了Draveness的文章Swift 類構(gòu)造器的使用檩奠,文章介紹的很詳細(xì)。
-
指定構(gòu)造器designated initialize
指定構(gòu)造器是類的主要構(gòu)造器附帽,要在指定構(gòu)造器中初始化所有的屬性埠戳,并且要在調(diào)用父類合適的指定構(gòu)造器。每個(gè)類應(yīng)該只有少量的指定構(gòu)造器蕉扮,大多數(shù)類只有一個(gè)指定構(gòu)造器整胃,我們使用 Swift 做 iOS 開(kāi)發(fā)時(shí)就會(huì)用到很多UIKit框架類的指定構(gòu)造器, 比如說(shuō):
init()
init(frame: CGRect)
init(style: UITableViewCellStyle, reuseIdentifier: String?)
當(dāng)定義一個(gè)指定構(gòu)造器的時(shí)候, 必須調(diào)用父類的某一個(gè)指定構(gòu)造器:
init(imageName: String, prompt: String = "") {
super.init(style: .Default, reuseIdentifier: nil)
}
-
便利構(gòu)造器convenience initialize
便利構(gòu)造器是類的次要構(gòu)造器, 你需要讓便利構(gòu)造器調(diào)用同一個(gè)類中的指定構(gòu)造器, 并將這個(gè)指定構(gòu)造器中的參數(shù)填上你想要的默認(rèn)參數(shù)。
如果你的類不需要便利構(gòu)造器的話喳钟,那么你就不必定義便利構(gòu)造器, 便利構(gòu)造器前面必須加上convenience
關(guān)鍵字爪模。
在這里我們就不舉例了, 但是我們要提一下便利構(gòu)造器的語(yǔ)法:
convenience init(name: String?, user_id: String?) {
self.init()
self.name = name
self.user_id = user_id
}
其中調(diào)用self.init()
時(shí),相當(dāng)于調(diào)用類的designated initialize方法荚藻,即調(diào)用ClassName()
,該類中所有的變量都會(huì)被使用默認(rèn)值進(jìn)行初始化屋灌。
-
init規(guī)則
定義 init 方法必須遵循三條規(guī)則:
-
指定構(gòu)造器必須調(diào)用它直接父類的指定構(gòu)造器方法。
-
便利構(gòu)造器必須調(diào)用同一個(gè)類中定義的其它初始化方法应狱。
-
便利構(gòu)造器在最后必須調(diào)用一個(gè)指定構(gòu)造器共郭。
只有指定構(gòu)造器才可以調(diào)用父類的指定構(gòu)造器,而便利構(gòu)造器是不可以的,這也遵循了這的三條規(guī)則除嘹。
-
init 的繼承和重載
跟 OC 不同写半,Swift 中的子類默認(rèn)不會(huì)繼承來(lái)自父類的所有構(gòu)造器。這樣可以防止錯(cuò)誤的繼承并使用父類的構(gòu)造器生成錯(cuò)誤的實(shí)例(可能導(dǎo)致子類中的屬性沒(méi)有被賦值而正確初始化)尉咕。與方法不同的一點(diǎn)是, 在重載構(gòu)造器的時(shí)候, 你不需要添加
override
關(guān)鍵字叠蝇。
雖然子類不會(huì)默認(rèn)繼承來(lái)自父類的構(gòu)造器,但是我們也可以通過(guò)別的方法來(lái)自動(dòng)繼承來(lái)自父類的構(gòu)造器年缎,構(gòu)造器的繼承就遵循以下的規(guī)則:
-
如果子類沒(méi)有定義任何的指定構(gòu)造器悔捶,那么會(huì)默認(rèn)繼承所有來(lái)自父類的指定構(gòu)造器。
-
如果子類提供了所有父類指定構(gòu)造器的實(shí)現(xiàn)单芜,不管是通過(guò)上面的規(guī)則繼承過(guò)來(lái)的蜕该,還是通過(guò)自定義實(shí)現(xiàn)的,它將自動(dòng)繼承所有父類的便利構(gòu)造器洲鸠。
-
構(gòu)造器總結(jié)
Swift 中構(gòu)造器需要遵循的規(guī)則還是很多的堂淡,總結(jié)一下,有以下規(guī)則:
- 調(diào)用相關(guān)
- 指定構(gòu)造器必須調(diào)用它直接父類的指定構(gòu)造器方法扒腕。
- 便利構(gòu)造器必須調(diào)用同一個(gè)類中定義的其它初始化方法绢淀。
- 便利構(gòu)造器在最后必須調(diào)用一個(gè)指定構(gòu)造器。
- 屬性相關(guān)
- 指定構(gòu)造器必須要確保所有被類中提到的屬性在代理向上調(diào)用父類的指定構(gòu)造器前被初始化瘾腰,之后才能將其它構(gòu)造任務(wù)代理給父類中的構(gòu)造器更啄。
- 指定構(gòu)造器必須先向上代理調(diào)用父類中的構(gòu)造器,然后才能為任意屬性賦值居灯。
- 便利構(gòu)造器必須先代理調(diào)用同一個(gè)類中的其他構(gòu)造器祭务,然后再為屬性賦值。
- 構(gòu)造器在第一階段構(gòu)造完成之前怪嫌,不能調(diào)用任何實(shí)例方法义锥,不能讀取任何實(shí)例屬性的值,self 不能被引用岩灭。
- 繼承相關(guān)
- 如果子類沒(méi)有定義任何的指定構(gòu)造器拌倍,那么會(huì)默認(rèn)繼承所有來(lái)自父類的指定構(gòu)造器。
- 如果子類提供了所有父類指定構(gòu)造器的實(shí)現(xiàn)噪径,不管是通過(guò)上一條規(guī)則繼承過(guò)來(lái)的柱恤,還是通過(guò)自定義實(shí)現(xiàn)的,它將自動(dòng)繼承所有父類的便利構(gòu)造器找爱。
說(shuō)了這么多梗顺,上個(gè)例子給大家感受下,比如我們自己寫(xiě)了一個(gè)基類MyViewController
繼承自UIViewController
车摄,然后在使用時(shí)寺谤,又寫(xiě)了一個(gè)類FirstViewController
繼承自剛才寫(xiě)的MyViewController
仑鸥,在MyViewController
中有一個(gè)函數(shù),后面的子類在實(shí)例化時(shí)都會(huì)調(diào)用這個(gè)基類的函數(shù)变屁,并且這個(gè)函數(shù)由MyViewController
的一個(gè)指定帶參的構(gòu)造器調(diào)用眼俊,最后我們希望在創(chuàng)建FirstViewController
的實(shí)例時(shí)使用FirstViewController()
這樣的方式,寫(xiě)的代碼就像這樣:
//首先粟关,基類代碼
import UIKit
class MyViewController: UIViewController {
//聲明一個(gè)屬性疮胖,默認(rèn)是公開(kāi)的
var color: UIColor
//寫(xiě)一個(gè)指定初始化器,需要調(diào)用父類指定構(gòu)造器
init(color: UIColor) {
//需要在調(diào)用父類的指定構(gòu)造器前完成本類所有屬性的初始化工作
self.color = color
//調(diào)用父類的其中一個(gè)指定初始化器
super.init(nibName: nil, bundle: nil)
self.initUI()
}
//要寫(xiě)本類的指定初始化器就要實(shí)現(xiàn)父類要求的指定構(gòu)造器
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
func initUI() {
let view = UIView.init(frame: CGRect.init(x: 100, y: 100, width: 100, height: 100))
self.view.addSubview(view)
view.backgroundColor = self.color
}
}
//基類的子類代碼
import UIKit
class FirstViewController: MyViewController {
override func viewDidLoad() {
super.viewDidLoad()
}
//覆載父類的指定構(gòu)造器
override init(color: UIColor) {
super.init(color: color)
}
//新寫(xiě)一個(gè)便利構(gòu)造器闷板,需要調(diào)用本類的指定構(gòu)造器
convenience init() {
self.init(color: .cyan)
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
這樣即完成了這兩個(gè)類的初始化設(shè)置澎灸,比如這時(shí)候我們?cè)谄渌目刂破髦姓{(diào)用FirstViewController
時(shí),只需要寫(xiě)FirstViewController()
即會(huì)調(diào)用MyViewController
中的initUI()
函數(shù)了蛔垢。