寫在開頭 iOS開發(fā)者 群173499350 給大家提供一個(gè)交流技術(shù) 也可以聊天打屁的平臺(tái)
翻譯自Swift官方Blog
- 我們?cè)谟胹wift設(shè)計(jì)開發(fā)時(shí)的一個(gè)重點(diǎn)就是 如何提高編碼模型的內(nèi)存安全問題 本文講解了一個(gè)內(nèi)存安全的問題 :
如何確保變量有一個(gè)初始值才能使用邢疙。
- swift版簡(jiǎn)介
變量什么時(shí)候是安全的 地粪? 開發(fā)者認(rèn)為無論任何時(shí)候訪問一個(gè)變量時(shí) 都有一個(gè)值 而不是
nil
像其他編程語言 比如C 要求程序員對(duì)內(nèi)存模型的編程技術(shù)非常嚴(yán)格 但是這是有風(fēng)險(xiǎn)的 人總會(huì)犯錯(cuò)C++
和OC
用了其他方式改善這種可能造成錯(cuò)誤的地方 如OC[nil message]
會(huì)被忽視 有的語言要求更嚴(yán)格 不賦值 就無法編譯
目前解決這種辦法采用的技術(shù)是讓編譯器執(zhí)行數(shù)據(jù)流分析 如果變量不初始化無法編譯通過 像java
C#
都采用這種技術(shù) Definitive Initialization
注意Swift不僅僅使用這一項(xiàng)技術(shù)
-
初始化一個(gè)局部變量
類型推斷允許你這樣寫var myInstance : MyClass // 定義一個(gè)非可選的局部變量 if x > 42 { myInstance = MyClass(intValue: 13) } else { myInstance = MyClass(floatValue: 92.3) } // myInstance已經(jīng)初始化 所以在下面可以使用 myInstance.printIt()
這里很簡(jiǎn)單的可以確定變量已經(jīng)初始化 可以保證不會(huì)訪問那些未初始化的內(nèi)存 避免Crash 但是有時(shí)候流程可能更加復(fù)雜
var myInstance : MyClass
if x > 10 {
myInstance = MyClass(intValue: 13)
}
// ...其他操作
if x > 42 {
myInstance.printIt()
}
這時(shí)編譯器可能告訴你 “Variable myInstance used before initialized” on the call to printIt()
其實(shí)就是說變量未初始化 編譯器不可能做所有預(yù)測(cè) 或者類型推斷 這就要求我們不要寫這么復(fù)雜的邏輯 去初始化一個(gè)變量
在普通數(shù)據(jù)類型如int 初始化時(shí)可以直接這樣
var index = 0
但是其他情況可能就要用到init()
- 其他技術(shù)補(bǔ)充
鑒于C語言的兼容性 有時(shí)候我們需要使用一些C不安全的API 如
UnsafePointer
這樣的代碼會(huì)造成程序運(yùn)行時(shí)Crash 這就要求程序員永遠(yuǎn)不犯錯(cuò)
- 隱式初始化
有些編程語言會(huì)有一些默認(rèn)值 比如聲明一個(gè)變量 int a未給這個(gè)變量賦值的情況下 我們就給一個(gè)默認(rèn)值 r如0 但是Swift 沒有采用這種考慮 原因如下
如果有些Protocol沒有要求實(shí)現(xiàn)init()方法 這樣一個(gè)變量就可能引用一個(gè)未初始化的對(duì)象 遺留在Cocoa編程中 這種情況太常見了
就算不給變量默認(rèn)值 自己寫一個(gè)也并不麻煩 而且會(huì)提前發(fā)現(xiàn)很多錯(cuò)誤 使代碼更容易維護(hù)
注意 只有可選類型或者隱式可選默認(rèn)值才是nil
所以Swift采用了 訪問一個(gè)變量前必須初始化