關於weak與lazy修飾字

記憶體管理是一個很重要的議題,如果沒有好好妥善管理的話,會導致應用程式閃退的,繼上一篇ARC文章主題,在這邊複習一下weak修飾字順便加碼介紹一下lazy修飾字,如何利用這兩個修飾字解決記憶體leak和節省記憶體的使用。

weak

在option的變數宣告時前面加上weak,代表弱參考型別的意思,在ARC的機制裡面弱型別在該物件被釋放時,不管該物件變數是否有參考其他物件,皆會強制被釋放掉。

備註:weak 變數必須是 optional 型別的。

class Person {   
var name: String
var age: Int
weak var lover: Person?
   init(name: String, age: Int) {        
self.name = name
self.age = age
}

deinit {
print("\(self.name) is dead...")
}
}
// 生成Mark和Jenny物件
var mark: Person! = Person(name: "mark", age: 25)
var jenny: Person! = Person(name: "jenny", age: 20)
mark.lover = jenny// Mark的愛人為Jenny
jenny.lover = mark// Jenny的愛人為Mark

Mark和Jenny是愛人關係,所以彼此互相愛著對方(參考對方)

接下來如果嘗試讓Mark死去(記憶體釋放),因為宣告時有加上weak修飾字的關係deinit()可被呼叫出來,代表Mark死去了,Jenny也跟Mark一樣,因為weak修飾字的關係,可以為對方殉情(記憶體釋放)。

mark = nil // mark is dead ...
jenny = nil // jenny is dead ...

備註:其實 xCode 有內建的工具且有兩種方式可用來查看是否有記憶體 leak 的問題,以下就分別來說明如何使用它們。在開始之前,為了演示 leak 的狀況,請將變數 lover 前的 weak 修飾字拿掉。

一、使用Debug Memory Graph 查看記憶體leak

執行模擬器以後,點選Debug Memory Graph

接著點選左側選單下面的Show only leaked block

接著就會看到兩個 leaked 物件,就可以了解有哪些物件沒被釋放掉了。

最後試著再把 weak 修飾字加回去再執行看看結果為何?

二、使用Profile來查看記憶體leak

在還沒有啟動模擬器之前,選擇Profile

選擇 Leaks

接著點選 command + R 來啟動模擬器,啟動後將會看到有兩個 leak 的物件。

最後試著再把 weak 修飾字加回去再執行看看結果為何?


lazy

延遲載入,在變數前加上 lazy,但該變數必須有初始值。

而且不得為常數,當物件生成的時侯(也就是 init),若是有加上 lazy 的變數,則不會立刻生成,當需要被使用到的時侯才會生成。

//模擬一個年資演算法
func calWorkAge(userName: String) -> Float {
   //計算年資
return 0
}
class User {
   var name: String!
   lazy var workAge: Float = 0
   init(name: String, workAge: Float) {
      self.name = name
      self.workAge = calWorkAge(userName: self.name)
}
}
let user: User = User(name: "Mark", workAge: 0)

因為宣告時有使用lazy修飾字,所以在init區塊裡面的workAge並不會立即被建立,則會等到要使用時,才會建立。

One clap, two clap, three clap, forty?

By clapping more or less, you can signal to us which stories really stand out.