iT邦幫忙

2018 iT 邦幫忙鐵人賽
DAY 23
0
Software Development

30天Swift入門學習系列 第 23

Swift Retain Cycle

開始講 retain cycle 前,先來講解 Swift 中記憶體的回收機制 ARC(Automatic Reference Counting)。
在 iOS 中每個 App 在執行時皆會被自動配置一定數量的記憶體好讓 App 內所宣告的物件能正常使用,當物件的生命週期結束時會參照 reference count 來將該物件所佔用之記憶體數量釋放回 App 所能使用之記憶體總量中。

在開發任何程式時一定會遇到一個相同的問題: Memory Leak。造成 memory leak 的主因是開發過程一直跟系統要求動態配置記憶體卻沒有進行記憶體釋放,導致記憶體被強制佔用直到整個程式生命週期結束(包含正常結束與被強制結束)。雖然 Swift 中會透過 ARC 來輔助釋放記憶體減輕開發者的負擔,但實際上仍常出現 memory Leak。

這邊舉個因 retain cycle 而導致 memory Leak 的例子:
宣告兩個物件 People 跟 Macbook:

class People {
  let name: String
  var macbook: Macbook?
  
  init(name: String, macbook: Macbook?) {
    self.name = name
    self.macbook = macbook
  }
  
  deinit {
    print("\(name) is being deinitialized.")
  }
}

class Macbook {
  let name: String
  var owner: People?
  
  init(name: String, owner: People?) {
    self.name = name
    self.owner = owner
  }
  
  deinit {
    print("Macbook named \(name) is being deinitialized.")
  }
}

初始化宣告好的物件:

var gavin: People? = People(name: "Gavin", macbook: nil)
var computer: Macbook? = Macbook(name: "Matilda", owner: nil)

先來將兩個物件 deinit 確定會不會產生 retain cycle:

gavin = nil
// print "Gavin is being deinitialized."
computer = nil
// print "Macbook named Matilda is being deinitialized."

因可正常印出 deinit()的內容所以可以確定沒有 retain cycle 的情況發勝。接下來要讓兩個物件彼此 reference 來產生 retain cycle:

gavin?.macbook = computer
computer?.owner = gavin

經過上一步驟後在將兩物件分別 deinit,此時是否會印出文字? 答案是.....什麼都沒印出。
上述的行為中因兩物件會彼此 reference 最後導致了 memory leak。

解決上述問題的方法很簡單,只需在會產生相互 reference 的 property 加上 weak 屬性即可解決此問題。

class Macbook {
  let name: String
  weak var owner: People?
  
  init(name: String, owner: People?) {
    self.name = name
    self.owner = owner
  }
  
  deinit {
    print("Macbook named \(name) is being deinitialized.")
  }
}

Reference
Automatic Reference Counting


上一篇
iOS App 實作(17) Shake Detect
下一篇
iOS App 實作(18) UserDefaults
系列文
30天Swift入門學習30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

1 則留言

0
stancth
iT邦新手 5 級 ‧ 2018-09-12 14:28:52

第一次宣告
var owner: Human?
應該為
var owner: People?
才是

吳晉榮 iT邦新手 5 級 ‧ 2018-09-12 22:34:27 檢舉

Thanks for correcting.

我要留言

立即登入留言