[筆記] Swift深入淺出常見語法 – Automatic Reference Counting (ARC)

black and blue butterfly illustration
分享

一個”正常”物件(Object) 的生命週期

  1. Allocation: Takes memory from a stack or heap.
  2. Initializationinit code runs.
  3. Usage.
  4. Deinitializationdeinit code runs.
  5. Deallocation: Returns memory to a stack or heap. (If not, Memory Leak)

而Swift透過”自動算數 (ARC)”的機制來判斷物件是否還被使用:
init => count + 1
deinit => count – 1

什麼時候該為Object加上 weak / unowned?

兩個Object之間有關連,就會形成Reference(Strong / Weak / Unowned),沒特別宣告,Swift會認定為Strong。

Apple’s Documentation recommends that a parent object should have a strong hold on a child object by convention — not the other way around.

class Parent {
    var child: Child?
}

class Child {
    unowned var parent: Parent
}

Capture Lists

var x = 5
var y = 5

let someClosure = { [x] in
  // [x] <---- 這個就是Capture Lists
  print("\(x), \(y)")
}
x = 6
y = 6

someClosure()        // Prints 5, 6
print("\(x), \(y)")  // Prints 6, 6

Cycles with Value Types & Reference Types

Value Types之間不會存在Cycles,Compile也不會過,例如:

// struct is a value type
struct Node {
  var payload = 0
  var next: Node? // <-- compile error!
}

// class is a reference type
class Node {
  var payload = 0
  var next: Node? // --> it is ok!
}

// what if ...
class Person {
  var name: String
  var friends: [Person] = [] // <-- compiled but not deallocated
  // unowned var friends: [Person] = [] // <-- and it's not allowed to use unowned
}

// we need to create a generic wrapper
class Unowned<T: AnyObject> {
  unowned var value: T
  init (_ value: T) {
    self.value = value
  }
}

class Person {
  var name: String
  
  var friends: [Unowned<Person>] = [] // <-- wrap 'Person'
}

參考資料:

  1. ARC and Memory Management in Swift

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *