Swift學(xué)習(xí)筆記--高級(jí)篇

最近看了兩本書(shū), 第一本是Objc.io出的Advanced Swift和王巍大大出的Swifter tips. 后者在作者的博客上有更新, 應(yīng)該已經(jīng)更新完了吧.

這里列出一些看過(guò)了筆記, 也是比較粗糙, 只是大概都過(guò)了一遍, 把一些之前遺漏或者有錯(cuò)漏的地方補(bǔ)全了.

一. Collection
1.值類(lèi)型的賦值雖然是copy, 但是實(shí)際上會(huì)是"copy on write”, 只有在真正發(fā)生寫(xiě)操作的時(shí)候才會(huì)進(jìn)行修改;
2.需要用for循環(huán)遍歷的時(shí)候考慮一下map函數(shù), 它可以使得代碼更加簡(jiǎn)潔, 同時(shí)可以讓原本不得不為var的變量變?yōu)閘et;3.為了避免不必要的copy, 數(shù)組的范圍下標(biāo)訪問(wèn)返回的集合是ArraySlice<T>類(lèi)型的, 它有與數(shù)組一樣的方法, 所以可以被當(dāng)做數(shù)組, 如果實(shí)在需要轉(zhuǎn)換就用Array(slice)來(lái)構(gòu)造一個(gè);
需要注意的是, 切面可以增加數(shù)組元素, 但是不能修改, 如下面的代碼:

var array = ["1","2","3"]
var slices = array[1..<array.endIndex]
slices[0] = “a”  // crash
slices.append("4”) // OK
// 存疑:
array[1] = “22”  // 執(zhí)行后slices并沒(méi)有響應(yīng)的變化, 所以, 對(duì)內(nèi)部實(shí)現(xiàn)還是有疑問(wèn)

4.Dictionary的updateValue方法可以返回舊值5.GeneratorType協(xié)議由于其只能被訪問(wèn)一次, 因此其實(shí)現(xiàn)者最好是class而不是struct6.對(duì)集合的訪問(wèn)盡量不要用subscript, 可以用for-in和map, filter等高階函數(shù)實(shí)現(xiàn), 幾個(gè)”特殊"的情況:1). 對(duì)下標(biāo)的遍歷: for idx in collection.indices2). 對(duì)下標(biāo)和元素的遍歷: for (idx, element) in collection.enumerate()7.嚴(yán)格說(shuō)來(lái)[1,2,3]這樣的值, 它的類(lèi)型不是Array, 而是ArrayLiteral, 只是因?yàn)锳rray實(shí)現(xiàn)了ArrayLiteralConvertible協(xié)議, 所以才能通過(guò)這樣的字面值來(lái)構(gòu)造Array, 同樣的還有DictionaryLiteralConvertible, IntegerLiteralConvertible,StringLiteralConvertible等等8.collection的starIndex不一定從0開(kāi)始的, 所以寫(xiě)C風(fēng)格循環(huán)的時(shí)候不要var i = 0, 而應(yīng)該是var i = collection.startIndex
9.case的模式匹配:

for case let variable? in mayNilCollection{
}

等同于:

for let variable in mayNilCollection where variable != nil {
}

同時(shí)

for case nil in mayNilCollection {

}

可以幫你找出集合中有多少個(gè)nil

同時(shí)case還可以和if一起用:

let j = 5
if case 0..<10 = j {

}
  1. lazy修飾符:
    lazy可以對(duì)屬性進(jìn)行修飾, 類(lèi)似于ObjC里面的手動(dòng)控制一樣. 同時(shí)Swift里面的標(biāo)準(zhǔn)庫(kù)也提供了一套lazy方法, 用起來(lái)是這樣的:
let data = 1...3
let result = data.lazy.map { (i: Int) -> Int in
  print("正在處理 \(i)")
  return i * 2
}
print("準(zhǔn)備訪問(wèn)結(jié)果")
for i in result {
  print("操作后結(jié)果為 \(i)")
}
print("操作完畢")
//輸出結(jié)果為:
// 準(zhǔn)備訪問(wèn)結(jié)果
// 正在處理 1
// 操作后結(jié)果為 2
// 正在處理 2
// 操作后結(jié)果為 4
// 正在處理 3
// 操作后結(jié)果為 6
// 操作完畢

可見(jiàn), 使用lazy可以把最后的計(jì)算拖到真正需要的時(shí)刻再進(jìn)行. 這種優(yōu)化非常適合在result遍歷的時(shí)候, 有需要退出的情況.

二. Optional
1.guard比if好的地方: guard let的變量可以被外部訪問(wèn), 避免了if金字塔結(jié)構(gòu); guard的語(yǔ)義更加鮮明, 就是為了檢查返回失敗條件的

  1. 關(guān)于optional chaining的結(jié)果也是optional的解釋:

let j = Int(“1”)?.successor().successor() // 為什么第二個(gè)successor()不需要加?來(lái)調(diào)用

原因在于結(jié)果是optional, 而不是中間狀態(tài)也是optional, 對(duì)于上面的語(yǔ)句來(lái)說(shuō), optional的狀態(tài)是已經(jīng)captured, 所以后續(xù)的方法調(diào)用只要不是前一個(gè)方法本身返回optional, 就不需要寫(xiě)?, 舉一個(gè)例證:

let j = Int(“1”)?.successor() // 這里把optional傳遞給了結(jié)果, 所以下面的語(yǔ)句需要加?
let k = j?.successor()

  1. 關(guān)于??操作符的解釋:
    ??操作符的作用基本可以等效為ObjC里面的?:操作符. 但是參考以下情況:
let i: Int? = nil
let j: Int? = nil
let k: Int? = 42
let m = i ?? j ?? k ?? 0
let n = i ?? j ?? k
print(“\(m)”)    // 說(shuō)明m的類(lèi)型是Int
print("\(n!)”)   // 說(shuō)明n的類(lèi)型是Int?

m和n的區(qū)別說(shuō)明, 對(duì)于編譯器來(lái)說(shuō), 不i j k是否為nil, m是可以確定不為nil的, 所以m不會(huì)為optional, 但是n則不一定. 這也算是optional的智能之處

另外, 用??來(lái)替代||和&&

if let n = i ?? j {
// 類(lèi)似于 if i != nil || j != nil
}

if let n = i, m = j {
// 類(lèi)似于 if i != nil && j != nil
}

主要注意的是, ??操作符要和多層optional一起使用的時(shí)候要特別注意, 如:

let s1: String?? = nil

(s1 ?? "inner") ?? “outer”     // 返回 “inner"
let s2: String?? = .Some(nil)
(s2 ?? "inner") ?? “outer”     // 返回 “outer"

4.Optional的map與flatMap

let stringNumbers = ["a","1", "2", "3"]
let x = stringNumbers.first.map{Int($0)}      // x的類(lèi)型為Int??
let y = stringNumbers.first.flatMap{Int($0)}  // y的類(lèi)型為Int?
  1. Optional類(lèi)型轉(zhuǎn)換
    在Optional值與非Optional值進(jìn)行比較的時(shí)候, Swift會(huì)對(duì)非Optional值進(jìn)行類(lèi)型轉(zhuǎn)換, 以使兩者類(lèi)型匹配, 再進(jìn)行比較. 這個(gè)特性被廣泛使用, 例如下面的代碼:
let strArray = [“1”, “2”, “3"]
let result = strArray.first.map{$0}

result的類(lèi)型會(huì)是String?, 但是map中返回的類(lèi)型是String, 所以是由Swift的編譯器為我們進(jìn)行了類(lèi)型轉(zhuǎn)換.

6.強(qiáng)制解包
無(wú)論出于什么樣的目的這么干, 一定要反思一下, 是否已經(jīng)沒(méi)有更好的選擇了? 這么寫(xiě)之后最好能留下注釋解釋為什么.

7.隱式Optional
隱式Optional本質(zhì)上還是Optional, 只是在使用的時(shí)候不需要再解包而已, 聲明如下:
var s :Int! = nil
print(“(s)”) // 不會(huì)報(bào)錯(cuò)

一般情況下, 會(huì)在那些的確有可能為空, 但是一旦初始化完成之后就不會(huì)為空的變量使用此類(lèi)型. 常見(jiàn)于某些提供了可能失敗的構(gòu)造器的情況.
需要注意的是, 如果隱式Optional為nil, 對(duì)它進(jìn)行的任何操作同樣會(huì)造成運(yùn)行時(shí)error.

最后提一下Monad和Factor吧. 這個(gè)唐巧在自己的博客上更新了很多相關(guān)內(nèi)容, 貌似最新的Qcon講的也是這個(gè). 這個(gè)東西理解起來(lái)的確很難, 但其實(shí)也就是2個(gè)概念, 對(duì)于這2個(gè)概念的解釋, 我覺(jué)得唐巧的博客里面講的很細(xì)致, 一起分享給大家我認(rèn)為最核心的部分:

  1. 主要理解什么叫「封裝過(guò)的值」, 值被包含在容器中或者被Optional包含, 都可以理解為封裝過(guò)的值.
  2. flatMap和map都是處理封裝過(guò)的值, 前者的閉包接受一個(gè)「未封裝的值」瘩例,返回一個(gè)「封裝后的值」, 后者閉包接受一個(gè)「未封裝的值」澄成,返回一個(gè)「未封裝的值」.

理解起來(lái)是比較繞, 但是一般來(lái)說(shuō)看看源碼, 知道這2個(gè)高級(jí)函數(shù)有什么用就會(huì)容易理解很多.

另外, Advanced Swift這本書(shū)還是挺值得看的, 很多內(nèi)容的確比較新穎, 會(huì)看到很多國(guó)內(nèi)的大牛都講了里面的一部分東西, 這里面算是集大成之作. 后續(xù)的幾章因?yàn)闀簳r(shí)團(tuán)隊(duì)還沒(méi)有用Swift開(kāi)發(fā), 所以還沒(méi)看, 對(duì)類(lèi)和結(jié)構(gòu)體的那一章也是老生常談, 如果發(fā)現(xiàn)有新大陸會(huì)更新出來(lái).

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子收擦,更是在濱河造成了極大的恐慌开财,老刑警劉巖始鱼,帶你破解...
    沈念sama閱讀 217,542評(píng)論 6 504
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件千埃,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡赠堵,警方通過(guò)查閱死者的電腦和手機(jī)小渊,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,822評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)茫叭,“玉大人酬屉,你說(shuō)我怎么就攤上這事∽岢睿” “怎么了呐萨?”我有些...
    開(kāi)封第一講書(shū)人閱讀 163,912評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)莽囤。 經(jīng)常有香客問(wèn)我谬擦,道長(zhǎng),這世上最難降的妖魔是什么朽缎? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,449評(píng)論 1 293
  • 正文 為了忘掉前任惨远,我火速辦了婚禮谜悟,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘北秽。我一直安慰自己葡幸,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,500評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布羡儿。 她就那樣靜靜地躺著礼患,像睡著了一般是钥。 火紅的嫁衣襯著肌膚如雪掠归。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 51,370評(píng)論 1 302
  • 那天悄泥,我揣著相機(jī)與錄音虏冻,去河邊找鬼。 笑死弹囚,一個(gè)胖子當(dāng)著我的面吹牛厨相,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播鸥鹉,決...
    沈念sama閱讀 40,193評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼蛮穿,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了毁渗?” 一聲冷哼從身側(cè)響起践磅,我...
    開(kāi)封第一講書(shū)人閱讀 39,074評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎灸异,沒(méi)想到半個(gè)月后府适,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,505評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡肺樟,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,722評(píng)論 3 335
  • 正文 我和宋清朗相戀三年檐春,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片么伯。...
    茶點(diǎn)故事閱讀 39,841評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡疟暖,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出田柔,到底是詐尸還是另有隱情俐巴,我是刑警寧澤,帶...
    沈念sama閱讀 35,569評(píng)論 5 345
  • 正文 年R本政府宣布凯楔,位于F島的核電站窜骄,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏摆屯。R本人自食惡果不足惜邻遏,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,168評(píng)論 3 328
  • 文/蒙蒙 一糠亩、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧准验,春花似錦赎线、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,783評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至另锋,卻和暖如春滞项,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背夭坪。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,918評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工文判, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人室梅。 一個(gè)月前我還...
    沈念sama閱讀 47,962評(píng)論 2 370
  • 正文 我出身青樓戏仓,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親亡鼠。 傳聞我的和親對(duì)象是個(gè)殘疾皇子赏殃,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,781評(píng)論 2 354

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

  • 背景 一年多以前我在知乎上答了有關(guān)LeetCode的問(wèn)題, 分享了一些自己做題目的經(jīng)驗(yàn)。 張土汪:刷leetcod...
    土汪閱讀 12,744評(píng)論 0 33
  • SwiftDay011.MySwiftimport UIKitprintln("Hello Swift!")var...
    smile麗語(yǔ)閱讀 3,836評(píng)論 0 6
  • 1间涵、隨機(jī)數(shù) 不需要隨機(jī)數(shù)種子 arc4random()%N + begin:產(chǎn)生begin~begin+N的隨機(jī)數(shù)...
    我是小胡胡123閱讀 4,162評(píng)論 0 2
  • 基礎(chǔ)部分(The Basics) 當(dāng)推斷浮點(diǎn)數(shù)的類(lèi)型時(shí)仁热,Swift 總是會(huì)選擇Double而不是Float。 結(jié)合...
    gamper閱讀 1,288評(píng)論 0 7
  • 湖南人愛(ài)吃浑厚,在全國(guó)都比較有名股耽。每到吃龍蝦的季節(jié),大街小巷钳幅,到處飄蕩著龍蝦的香味物蝙,引得人口水直流。今天敢艰,劉家弟弟親自...
    劉姐之家閱讀 389評(píng)論 4 0