/**
* swift使用自動引用計數(arc)來管理應用程式的記憶體使用。這表示記憶體管理已經是swift的一部分,在大多數情況下,你並不需要考慮記憶體的管理。當例項並不再被需要時,arc會自動釋放這些例項所使用的記憶體。
另外需要注意的:
引用計數僅僅作用於類例項上。結構和列舉是值型別,而非引用型別,所以不能被引用儲存和傳遞。
swift的arc工作過程
每當建立乙個類的例項,arc分配乙個記憶體塊來儲存這個例項的資訊,包含了型別資訊和例項的屬性值資訊。
另外當例項不再被使用時,arc會釋放例項所占用的記憶體,這些記憶體可以再次被使用。
但是,如果arc釋放了正在被使用的例項,就不能再訪問例項屬性,或者呼叫例項的方法了。直接訪問這個例項可能造成應用程式的崩潰。就像空例項或游離例項一樣。
為了保證需要例項時例項是存在的,arc對每個類例項,都追蹤有多少屬性、常量、變數指向這些例項。當有活動引用指向它時,arc是不會釋放這個例項的。
為實現這點,當你將類例項賦值給屬性、常量或變數時,指向例項的乙個強引用(strong reference)將會被構造出來。被稱為強引用是因為它穩定地持有這個例項,當這個強引用存在時,例項就不能夠被自動釋放,因此可以安全地使用。
*/class
student
func getname() -> string
func listening()
deinit
}class
teacher
func getname() -> string
func classing()
deinit
}func testarc()
testarc()
/*** 從上面的例子來看,確實swift給我們自動管理了記憶體,很多時侯開發者都不需要考慮太多的記憶體管理。但真的是這樣嗎?真的安全嗎?作為開發者要如何用好arc?
儘管arc減少了很多記憶體管理工作,但arc並不是絕對安全的。下面來看一下迴圈強引用導至的記憶體洩漏。
*/func testmemoryleak()
/**例項之間的相互引用,在日常開發中是很常見的一種,哪麼如何避免這種迴圈強引用導致的記憶體洩漏呢?
可以通過在類之間定義為弱引用(weak)或無宿主引用的(unowned)變數可以解決強引用迴圈這個問題
*/testmemoryleak()
/*** 弱引用方式:
弱引用並不保持對所指物件的強烈持有,因此並不阻止arc對引用例項的**。這個特性保證了引用不成為強引用迴圈的一部分。指明引用為弱引用是在生命屬性或變數時在其前面加上關鍵字weak。
注意弱引用必須宣告為變數,指明它們的值在執行期可以改變。弱引用不能被宣告為常量。
因為弱引用可以不含有值,所以必須宣告弱引用為可選型別。因為可選型別使得swift中的不含有值成為可能。
加上weak var student : student?
或weak var teacher : teacher?
經測試得出結論:
當a類中包函有b類的弱引用的例項,同時,b類中存在a的強引用例項時,如果a釋放,也不會影響b的析放,但a的記憶體**要等b的例項釋放後才可以**。(情況一的結果)
當a類中包函有b類的強引用的例項時,如果a釋放,則不會影響b的析放。(情況二的結果)
*//**
* 無宿主引用方式:
和弱引用一樣,無宿主引用也並不持有例項的強引用。但和弱引用不同的是,無宿主引用通常都有乙個值。因此,無宿主引用並不定義成可選型別。指明為無宿主引用是在屬性或變數宣告的時候在之前加上關鍵字unowned。
因為無宿主引用為非可選型別,所以每當使用無宿主引用時不必使用?。無宿主引用通常可以直接訪問。但是當無宿主引用所指例項被釋放時,arc並不能將引用值設定為nil,因為非可選型別不能設定為nil。
注意在無宿主引用指向例項被釋放後,如果你想訪問這個無宿主引用,將會觸發乙個執行期錯誤(僅當能夠確認乙個引用一直指向乙個例項時才使用無宿主引用)。在swift中這種情況也會造成應用程式的崩潰,會有一些不可預知的行為發生。因此使用時需要特別小心。
*/class
teacher1
func getname() -> string
func classing()
deinit
}class
student1
func getname() -> string
func listening()
deinit
}func testnotowner()
/*** 所以使用無宿主引用時,就需要特別小心,小心別人釋放時,順帶釋放了強引用物件,所以要想別人釋放時不影響到原例項,可以使用弱引用這樣就算nil,也不會影響。
*/testnotowner()
/*** 上面介紹了,當某個類中的例項物件如果在整個生命週期中,有某個時間可能會被設為nil的例項,使用弱引用,如果整個生命週期中某一例項,一旦構造,過程中不可能再設為nil的例項變數,通常使用無宿主引用。但時有些時侯,在兩個類中的相互引用屬性都一直有值,並且都不可以被設定為nil。這種情況下,通常設定乙個類的例項為無宿主屬性,而另乙個類中的例項變數設為的隱式裝箱可選屬性(即!號屬性)
如下面的例子,每位父親都有孩子(沒孩子能叫父親麼?),每個孩子都有乙個親生父親
*///class children
////
// deinit
//
//}//class father
////
// deinit
//
//}//
////var fa = father(name: "王五",childname: "王八")
//print("\(fa.fathername) 有個小孩叫 \(fa.children.name)")
////另外,還有一種情況,當自身的閉包對自身(self) 的強引用,也會導致記憶體洩漏。
class
cpufactory
//宣告乙個閉包
lazy
var someclosure: (int, string) -> string =
//宣告乙個閉包,同樣閉包中引用self
lazy
var machining: () -> string =
else
}//宣告乙個閉包,但閉包中將自身作為引數傳進去(可以避去記憶體洩漏)
lazy
var machining2 : (cpufactory) -> string =
else
}deinit
}//在這個例子中有三個閉包,分別是帶參,和不帶參,對於帶參的 不能省略[unowned self] (paramers) in操作。否則會編譯不過,另外,書中沒有提到的,只有宣告為@lazy的閉包中才可以使用[unowned self] 否則在普通閉包中使用也會報錯。還有一點書中講到當自身閉包中使用self.時會產生強引用,導至記憶體洩漏,因此加上[unowned self ] in 這句可以破壞這種強引用,從而使記憶體得到釋放,但經本人親自驗證,就算加上了也沒有釋放。
func testclosure1()
testclosure1()
//顯然cpu = nil也不會釋放記憶體。
func testclosure2()
testclosure2()
//可見使用自身作為引數傳參時,可以釋放記憶體。
func testclosure3()
testclosure3()
//實第三和第一種是一樣的,都是引用了self.但第一種可以把[unowned self ]in 句注釋和不注釋的情況下進行測試,可以發現結果是一樣的,並沒有釋放記憶體。
///
Swift學習之自動引用計數
class person deinit var reference1 person?var reference2 person?var reference3 person?reference1 person name iyaqi 此時會列印 person iyaqi is being initial...
swift學習筆記 七 自動引用計數
與object c一樣,swift使用自動引用計數來跟蹤並管理應用使用的記憶體。當例項不再被使用時,及retaincount 0時,會自動釋放是理所占用的記憶體空間。注 引用計數僅適用於類的例項,因為struct和enumeration屬於值型別,也就不牽涉引用,所以其儲存和管理方式並不是引用計數。...
swift自動引用計數
在少數情況下,arc為了能幫助你管理記憶體,需要更多的關於你的 之間關係的資訊 引用計數僅僅應用於類的例項,結構體和列舉型別是值型別,不是引用型別,也不是通過引用的方式儲存和傳遞 為了使之成為可能,無論你將例項賦值給屬性,常量或者是變數,屬性,常量或者變數,都會對此例項建立強引用。之所以稱之為強引用...