iT邦幫忙

2024 iThome 鐵人賽

DAY 19
0
Mobile Development

Swift iOS UIKit 初學者系列:從零開始開發互動式應用系列 第 19

【Day 19】iOS 記憶體管理實驗:自動引用計數(ARC)與記憶體洩漏。

  • 分享至 

  • xImage
  •  

今天我們將深入探討 iOS 記憶體管理的核心機制——自動引用計數(Automatic Reference Counting, ARC)。我們將通過一個「吃掉記憶體」的實驗來觀察當強引用(strong reference)導致循環引用(retain cycle)時,記憶體如何被耗盡,並學習如何正確地解決這個問題以避免記憶體洩漏。

學習目標

  • 了解自動引用計數(ARC)的基本工作原理。
  • 探討強引用導致的循環引用問題及其解決方案。
  • 使用 Instruments 工具進行記憶體檢測,學習如何觀察內存使用和發現記憶體洩漏。

實驗目標

我們將進行兩個實驗:

  • 模擬強引用引發的循環引用,觀察記憶體無法被釋放的情況。
  • 使用弱引用或無主引用來解決循環引用問題,確認記憶體能夠正常釋放。

實驗過程影片

記憶體無法釋放的實驗。
Yes

強引用與弱引用實驗

實驗1 : 強引用(Strong Reference)導致的循環引用

操作步驟

首先,我們會創建兩個物件(Person 和 Apartment),並讓它們互相持有強引用。即便我們將它們設為 nil,由於彼此間存在強引用,記憶體將無法釋放,最終導致記憶體洩漏。

實驗程式碼

class Person {
    let name: String
    var apartment: Apartment? // 強引用
    init(name: String) { self.name = name }
}

class Apartment {
    let unit: String
    var tenant: Person? // 強引用
    init(unit: String) { self.unit = unit }
}

func testARC() {
    var jason: Person? = Person(name: String(repeating: "Jason", count: 1000000))
    var unit4A: Apartment? = Apartment(unit: "4A")
    
    jason?.apartment = unit4A
    unit4A?.tenant = jason

    jason = nil
    unit4A = nil
}

結果與觀察

可以看到,無論我們將 jason 和 unit4A 設為 nil,由於它們互相強引用,記憶體無法釋放,這導致了記憶體洩漏。

你可以點擊下面的影片查看這個過程:
Yes

執行後可以看到模擬器記憶體使用量持續上升,截圖顯示已經達到14GB,且繼續增加,這是典型的記憶體洩漏案例。

實驗2 :使用弱引用(Weak Reference)解決循環引用

在第二個實驗中,我們將修改其中一個引用為弱引用(weak reference),從而打破循環引用,確保記憶體能夠被正確釋放。

class Apartment {
    let unit: String
    weak var tenant: Person? // 弱引用,避免循環引用
}

結果與觀察

這次,當我們將 jason 和 unit4A 設為 nil 時,記憶體得以順利釋放。透過 Instruments 或 Xcode 工具可以看到記憶體不再持續上升,且無記憶體洩漏發生。

從下圖可以看見記憶體順利被釋放。

使用 Instruments 觀察記憶體使用情況

在 Xcode 中,選擇 Product > Profile,並選擇 Allocations 模板來檢測記憶體使用情況。或者,點擊 Memory Report 裡的「Profile in Instruments」按鈕,也可以打開 Instruments 來進行詳細檢查。

當檢測到記憶體洩漏時,會在 Instruments 中出現紅色的警示符號,如下圖所示:

總結

在這篇文章中,我們學習了 自動引用計數(ARC) 的基本工作原理,並通過實驗展示了強引用導致的循環引用問題以及如何使用弱引用來避免記憶體洩漏。掌握這些記憶體管理技巧,能幫助我們在開發過程中避免常見的記憶體問題,確保應用的穩定性與效能。

附錄:已接觸的 UIKit 主題

  • ARC(Automatic Reference Counting)(Day 19)– 探討 Swift 中的自動引用計數機制,並示範如何透過 weak 和 unowned 打破循環引用,避免記憶體洩漏問題。

上一篇
【Day 18】Core Data 的修煉-2:探索背後的 SQLite 資料庫結構
下一篇
【Day 20】iOS 開發實戰 - 顏文字遊戲 App:富文本的魅力與應用
系列文
Swift iOS UIKit 初學者系列:從零開始開發互動式應用30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言