📂
CMiOSBook
  • CMoney iOS Book
  • Coding 101
    • Value / Reference Type
    • ARC + Retain Cycle
    • 物件之間的溝通方式
  • 工具主題
    • 基本工具篇
    • Git 篇
  • 架構主題
    • MVC
  • CodingStyle主題
    • CodingStyle 規則
      • 專案(Project)
      • 命名(Naming)
      • 程式格式(Format)
      • 註解(Comment)
      • 類別與結構(Classes and Structures)
      • 修飾詞(Modifier)
      • 閉包表達式(Closures)
    • 靜態檢查器
    • 專案基本規定
  • UI主題
    • UIScrollViewDelegate & UITableViewDelegate
  • Charts主題
    • 簡介
    • Lesson1 Chart Setup
    • Lesson2 Chart Data
    • Lesson3 CombinedChartView
    • Lesson4 Renderer
  • Test主題
    • 單元測試的基本概念
    • XCTest-UnitTest
    • XCTest-UITest
  • 學習資源
    • 相關網站
    • 相關會議與社群
    • 計算機考題
Powered by GitBook
On this page
  • 課程文件
  • 如何找Retain Cycle
  • 方法一:使用 deinit,確認物件是否被消滅
  • 方法二:使用 Xcode 的 Debug Memory Graphic
  • 如何解決Retain Cycle
  • 情境一: 兩個類別互相擁有,加上weak即可!!!
  • 情境二:Delegate和Protocol,加上weak即可!!!
  • 情境三:被擁有的Closure,定義時請使用weak self即可!!!

Was this helpful?

  1. Coding 101

ARC + Retain Cycle

理解程式是如何管控記憶體並且正確地操作物件,可以避免記憶體的浪費。

PreviousValue / Reference TypeNext物件之間的溝通方式

Last updated 3 years ago

Was this helpful?

課程文件

  • 參考連結:

  • 範例連結:

如何找Retain Cycle

方法一:使用 deinit,確認物件是否被消滅

/// 人物
class People {
    let name: String = "John"
    var macbook: Macbook? = nil
    deinit {
        print("\(name) deinit.")
    }
}

/// 筆電
class Macbook {
    let name: String = "Macbook"
    var owner: People? = nil
    deinit {
        print("\(name) deinit.")
    }
}

方法二:使用 Xcode 的 Debug Memory Graphic

如何解決Retain Cycle

情境一: 兩個類別互相擁有,加上weak即可!!!

/// 人物
class People {
    let name: String = "John"
    var macbook: Macbook? = nil
    deinit {
        print("\(name) deinit.")
    }
}

/// 筆電
class Macbook {
    let name: String = "Macbook"
    weak var owner: People? = nil // <----- 必須加上weak才可以被釋放
    deinit {
        print("\(name) deinit.")
    }
}

情境二:Delegate和Protocol,加上weak即可!!!

protocol DataManagerDelegate: AnyObject {
    func didGetData()
}
class DataManager{
    weak var delegate: DataManagerDelegate? // <----- 必須加上weak才可以被釋放
    func getData(){
        delegate?.didGetData()
    }
}

class ViewContorller: UIViewController{
      private var dataManager = DataManager()
      override func viewDidLoad() {
        super.viewDidLoad()
        dataManager.delegate = self
        dataManager.getData()
    }
}
extension ViewContorller: DataManagerDelegate{
    func didGetData(){ ... }
}

情境三:被擁有的Closure,定義時請使用weak self即可!!!

class MemberManager{
    var didChangeMember: ((String) -> Void)?
    func changeMember(){
        didChangeMember?("更換會員")
    }
}

class TestClosure2ViewController: UIViewController {

    var label = UILabel()
    let memberManager = MemberManager()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        memberManager.didChangeMember = { 
            [weak self] value in // <----- Closure被Hold著,必須加上weak才可以被釋放
            guard let self = self else { return }
            self.label.text = value
        }
        
        memberManager.changeMember()
    }

    deinit {
        print("TestClosure2 deinit.")
    }
    
}
Automatic Reference Counting
Swift Retain Cycle
iOS_RetainCycleProject
Debug Memory Graphic