Automatic Reference Counting - The Swift Programming Language (Swift 5.1)
Swiftλ μ±μ λ©λͺ¨λ¦¬ μ¬μ©μ μΆμ νκ³ κ΄λ¦¬ νκΈ° μν΄ Automatic Reference Counting (ARC)λ₯Ό μ¬μ©ν©λλ€. λλΆλΆμ κ²½μ°, μ΄κ²μ Swiftμμ λ©λͺ¨λ¦¬ κ΄λ¦¬λ₯Ό "κ·Έλ₯ μλλλ€"λ κ²μ μλ―Ένκ³ , λΉμ μ΄ λ©λͺ¨λ¦¬ κ΄λ¦¬μ λν΄μ μκ° ν νμκ° μμ΅λλ€. ν΄λμ€ μΈμ€ν΄μ€μ μν΄ μ¬μ© λλ λ©λͺ¨λ¦¬κ° λμ΄μ νμ νμ§ μμ λ ARCλ λ©λͺ¨λ¦¬λ₯Ό ν΄μ ν©λλ€.
νμ§λ§, λͺλͺ μΌμ΄μ€μμ ARCλ λ©λͺ¨λ¦¬λ₯Ό κ΄λ¦¬ νκΈ° μν΄ λΉμ μ μ½λμ λΆλΆ κ°μ κ΄κ³μ λν λ λ§μ μ 보λ₯Ό μꡬν©λλ€. μ΄λ² μ±ν°μμλ κ·Έλ¬ν μν©λ€μ λν΄ μ€λͺ νκ³ ARCκ° λΉμ μ μ±μ λͺ¨λ λ©λͺ¨λ¦¬λ₯Ό κ΄λ¦¬ν μ μλλ‘ νλμ§ λ³΄μ¬μ€ κ²λλ€. Swiftμμ ARCλ₯Ό μ¬μ©νλ κ²μ Obective-Cλ‘ ARCλ₯Ό μ¬μ©νλ Transitioning to ARC Release Notesμμμ μ€λͺ κ³Ό λ§€μ° μ μ¬ν©λλ€.
Reference countingμ ν΄λμ€μ μΈμ€ν΄μ€μμλ§ μ μ© κ°λ₯ν©λλ€. ꡬ쑰체λ μ΄κ±°νμ μ°Έμ‘° νμ μ΄ μλ, κ° νμ μ΄κ³ λ νΌλ°μ€μ μν΄ μ μ₯λκ³ μ λ¬ λμ§ μμ΅λλ€.
ν΄λμ€μ μ μΈμ€ν΄μ€λ₯Ό μμ± ν λ λ§λ€, ARCλ μΈμ€ν΄μ€μ λν μ 보λ₯Ό μ μ₯ νκΈ° μν΄ λ©λͺ¨λ¦¬μ λ©μ΄λ¦¬λ₯Ό ν λΉν©λλ€. μ΄ λ©λͺ¨λ¦¬λ μΈμ€ν΄μ€μ νμ μ λν μ 보μ κ·Έ μΈμ€ν΄μ€μ κ΄λ ¨λ μ μ₯ νλ‘νΌν°μ κ°λ κ°μ§κ³ μμ΅λλ€.
μΆκ°μ μΌλ‘, μΈμ€ν΄μ€κ° λμ΄μ νμ μμ΄μ§λ©΄, ARCλ λ©λͺ¨λ¦¬κ° λ€λ₯Έ λͺ©μ μΌλ‘ μ¬μ© λμ΄ μ§ μ μλλ‘ κ·Έ μΈμ€ν΄μ€μ μν΄ μ¬μ© λ λ©λͺ¨λ¦¬λ₯Ό ν΄μ ν©λλ€. μ΄κ²μ ν΄λμ€ μΈμ€ν΄μ€κ° κ·Έλ€μ΄ λμ΄μ νμ μμ λ λ©λͺ¨λ¦¬μ 곡κ°μ μ°¨μ§ νκ³ μμ§ μλ€λ κ²μ 보μ₯ν©λλ€.
νμ§λ§, ARCκ° μ¬μ ν μ¬μ© λκ³ μλ μΈμ€ν΄μ€λ₯Ό ν΄μ νλ€λ©΄, μΈμ€ν΄μ€ νλ‘νΌν°μ λμ΄μ μ κ·Ό ν μ μκ±°λ, μΈμ€ν΄μ€μ λ©μλ€λ₯Ό νΈμΆ ν μ μμ΅λλ€. λ§μ½ μΈμ€ν΄μ€μ μ κ·Ό νλ € νλ€λ©΄, μ±μ λλΆλΆ μλ§λ ν¬λμκ° λ κ² μ λλ€.
μΈμ€ν΄μ€κ° μ¬μ© λλ λμμ μ¬λΌμ§μ§ μκ² νκΈ° μν΄μλ, ARCλ μΌλ§λ λ§μ νλ‘νΌν°, μμ, κ·Έλ¦¬κ³ λ³μλ€μ΄ νμ¬ κ°κ°μ ν΄λμ€ μΈμ€ν΄μ€μ μ°Έμ‘°λκ³ μλμ§ μΆμ ν©λλ€. ARCλ μ‘΄μ¬νλ μΈμ€ν΄μ€μ μ μ΄λ νλμ νμ±νλ λ νΌλ°μ€κ° μλ€λ©΄ μΈμ€ν΄μ€λ₯΄ ν΄μ νμ§ μμ κ² μ λλ€.
ν΄λμ€ μΈμ€ν΄μ€λ₯Ό νλ‘νΌν°, μμ νΉμ λ³μμ ν λΉ ν λ μΈμ λ μ§, νλ‘νΌν°, μμ, λ³μλ μ΄κ²μ κ°λ₯νκ² νκΈ° μν΄ μΈμ€ν΄μ€μ κ°ν μ°Έμ‘°λ₯Ό λ§λλλ€. μ΄ μ°Έμ‘°λ κ°ν μ°Έμ‘°λ‘ λΆλ¦½λλ€. μλνλ©΄ κ·Έ μΈμ€ν΄μ€μ λ¨λ¨ν κ³ μ μ μ μ§νκ³ , κ°ν μ°Έμ‘°κ° λ¨μ μλ ν ν΄μ λ₯Ό νμ©νμ§ μμ΅λλ€.
μ¬κΈ° Auto Reference Countingμ λμ λ°©μμ λν μμ κ° μμ΅λλ€. μ΄ μμ λ name
μ΄λΌλ μ μ₯ μμ νλ‘νΌν°λ₯Ό μ μνλ Person
μ΄λΌλ κ°λ¨ν ν΄λμ€λ‘ μμν©λλ€.
class Person {
let name: String
init(name: String) {
self.name = name
print("\(name)is being initialized")
}
deinit {
print("\(name)is being deinitialized")
}
}
Person
ν΄λμ€λ μΈμ€ν΄μ€μ name
νλ‘νΌν°λ₯Ό μΈν
νκ³ μ΄κΈ°νκ° μ§ν μ€μμ λνλ΄λ λ©μμ§λ₯Ό μΆλ ₯ ν΄μ£Όλ μμ±μλ₯Ό κ°κ³ μμ΅λλ€. Person
ν΄λμ€λ ν΄λμ€μ μΈμ€ν΄μ€κ° ν΄μ λ λ λ©μΈμ§λ₯Ό μΆλ ₯νλ μλ©Έμ λν κ°μ§κ³ μμ΅λλ€.
λ€μ μ½λλ Person
μΈμ€ν΄μ€λ₯Ό μμ±νκΈ° μν΄ μ¬μ© λλ λ€μμ μ°Έμ‘°λ₯Ό Person?
νμ
μ 3κ°μ λ³μλ₯Ό μ μνκ³ μμ΅λλ€. μ΄ λ³μλ€μ΄ μ΅μ
λ νμ
μ΄κΈ° λλ¬Έμ(Person
μ΄ μλ,Person?
), μλμΌλ‘ nil
κ°μΌλ‘ μ΄κΈ°ν λκ³ , νμ¬λ Person
μΈμ€ν΄μ€λ₯Ό μ°Έμ‘°νκ³ μμ§ μμ΅λλ€.
var reference1: Person?
var reference2: Person?
var reference3: Person?
μ΄μ μλ‘μ΄ Person
μΈμ€ν΄μ€λ₯Ό μ΄κΈ°ννκ³ 3κ° λ³μλ€ μ€ νλλ₯Ό ν λΉ ν μ μμ΅λλ€.
refernce1 = Person(name: "Jinha Park")
// Prints "Jinha Park is being initialized"
Person
ν΄λμ€μ μμ±μλ₯Ό νΈμΆνλ μμ μ "Jinha Park is being initialized" λΌλ λ©μΈμ§κ° μΆλ ₯λλ κ²μ μ£Όλͺ©νμΈμ. μ΄κ²μ μ΄κΈ°νκ° μ΄λ£¨μ΄μ‘λ€λ κ²μ νμΈν΄ μ€λλ€.
Person
μΈμ€ν΄μ€κ° reference1
λ³μμ ν λΉμ΄ λμκΈ° λλ¬Έμ, reference1
μμ Person
μΈμ€ν΄μ€μ κ°ν μ°Έμ‘°κ° λκ³ μμ΅λλ€. μ μ΄λ νλμ κ°ν μ°Έμ‘°κ° μκΈ° λλ¬Έμ, ARCλ Person
μ λ©λͺ¨λ¦¬μ μ μ§ μν€λλ‘ ν κ²μ΄κ³ ν΄μ λμ§ μμ΅λλ€.
κ°μ Person
μΈμ€ν΄μ€λ₯Ό λ κ°μ λ³μμ λ ν λΉνλ©΄, μΈμ€ν΄μ€μ λκ°μ κ°ν μ°Έμ‘°κ° μκΈ°κ² λ©λλ€.
refernce2 = refernce1
refernce3 = refernce1
μ¬κΈ°μ νλμ Person
μΈμ€ν΄μ€μ μΈκ°μ κ°ν μ°Έμ‘°κ° μμ΅λλ€.
λ§μ½ μ΄ λκ°μ κ°ν μ°Έμ‘°(κΈ°μ‘΄ μ°Έμ‘°λ₯Ό ν¬ν¨ν)λ₯Ό λκ°μ λ³μμ nilμ ν λΉμΌλ‘μ κΉ¨κ³ μΆλ€λ©΄, νλμ κ°ν μ°Έμ‘°λ λ¨μμκ³ , Person
μΈμ€ν΄μ€λ ν΄μ λμ§ μμ κ²μ
λλ€.
refernce1 = nil
refernce2 = nil
ARCλ μΈλ²μ§Έ κ·Έλ¦¬κ³ λ§μ§λ§ κ°ν μ°Έμ‘°κ° κΉ¨μ§κΈ° μ κΉμ§, Person
μΈμ€ν΄μ€λ₯Ό ν΄μ νμ§ μμ΅λλ€. Person
μΈμ€ν΄μ€λ₯Ό λμ΄μ μ¬μ© νμ§ μλ μμ μ ν΄μ λ©λλ€.
refernce3 = nil
// Prints "Jinha Park is being deinitialized"
μμ μμ μμ, ARCλ μμ±ν μλ‘μ΄ Person
μΈμ€ν΄μ€μ μ°Έμ‘°μ κ°μλ₯Ό μΆμ ν μ μκ³ Person
μΈμ€ν΄μ€κ° λμ΄μ νμ μμ λ ν΄μ ν μ μμ΅λλ€.
νμ§λ§, ν΄λμ€μ μΈμ€ν΄μ€μ κ°ν μ°Έμ‘°κ° 0 μ΄ λλ μμ μ΄ μ ν μκΈ°μ§ μλ μ½λλ₯Ό μμ±νκ² λ μλ μμ΅λλ€. μ΄κ²μ λ κ°μ ν΄λμ€ μΈμ€ν΄μ€κ° μλ‘ κ°ν μ°Έμ‘°λ₯Ό νκ³ , κ°κ°μ μΈμ€ν΄μ€κ° λ€λ₯Έ μΈμ€ν΄μ€λ₯Ό μ΄λ € λ κ²½μ°μ λ°μν μ μμ΅λλ€. μ΄κ²μ κ°ν μ°Έμ‘° μνμ΄λΌκ³ μλ €μ Έ μμ΅λλ€.
ν΄λμ€ κ°μ κ΄κ³λ₯Ό strong μ°Έμ‘° λμ weak λλ unowned μ°Έμ‘°λ‘ μ μ ν¨μΌλ‘μ¨ κ°ν μν μ°Έμ‘°λ₯Ό ν΄κ²° ν μ μμ΅λλ€. μ΄ κ³Όμ μ ν΄λμ€ μΈμ€ν΄μ€ κ°μ κ°ν μν μ°Έμ‘° ν΄κ²°νκΈ°(Resolving Strong Refernce Cycles Between Class Instances)μμ μ€λͺ λμ΄ μμ΅λλ€. νμ§λ§, κ°ν μ°Έμ‘° μνμ ν΄κ²° λ°©λ²μ λ°°μ°κΈ° μ μ, κ°ν μν μ°Έμ‘°κ° μ΄λ»κ² λ°μ νλμ§μ λν΄ μ΄ν΄νλ κ²μ΄ λμμ΄ λ κ² μ λλ€.
μ¬κΈ° κ°ν μν μ°Έμ‘°κ° μ΄λ»κ² μ°μ°ν μκΈ°λ μ§μ λν μμκ° μμ΅λλ€. μ΄ μμλ μννΈμ λ¨μ§μ κ±°μ£Όμμ λͺ¨λΈνν Person
κ³Ό Apartment
λΌλ ν΄λμ€λ₯Ό μ μ νκ³ μμ΅λλ€.
class Person {
let name: String
init(name: String) { self.name = name }
var apartment: Apartment?
deinit { print("\(name) is being deinitialized") }
}
class Apartment {
let unit: String
init(unit: String) { self.unit = unit }
var tenant: Person?
deinit { print("Apartment \(unit) is being deinitialized") }
}
λͺ¨λ Person
μΈμ€ν΄μ€λ String
μ°¨μ
μ name
νλ‘νΌν°μ nil
λ‘ μ΄κΈ°ν λ μ΅μ
λ νμ
μ apartment
νλ‘νΌν°λ₯Ό κ°μ§κ³ μμ΅λλ€. μ¬λμ΄ νμ μννΈλ₯Ό κ°μ§κ³ μμ§ μκΈ° λλ¬Έμ apartment
νλ‘νΌν°λ μ΅μ
λμ
λλ€.
μ μ¬νκ², λͺ¨λ Apartment
λ String
νμ
μ unit
κ³Ό nil
λ‘ μ΄κΈ°ν λ μ΅μ
λ νμ
tenant
μ κ°μ§κ³ μμ΅λλ€. μννΈμ νμ μΈμ
μκ° μλ κ²μ΄ μλκΈ° λλ¬Έμ μΈμ
μ νλ‘νΌν°λ μ΅μ
λ μ
λλ€.
λ ν΄λμ€ λͺ¨λ ν΄λμ€μ μΈμ€ν΄μ€κ° ν΄μ λμλ€λ μ¬μ€μ μΆλ ₯ ν΄μ£Όλ μλ©Έμλ₯Ό μ μνκ³ μμ΅λλ€. μ΄κ²μ Person
μ Apartment
μ μΈμ€ν΄μ€κ° μμλλ‘ ν΄μ λμλμ§λ₯Ό λ³Ό μ μκ² ν΄μ€λλ€.
λ€μ μ½λλ μλ μ½λμμ νΉμ Apartment
μ Person
μΈμ€ν΄μ€μ λμ
λ , μ΅μ
λ νμ
μΈ jinha
μ unit4A
λΌλ λκ°μ λ³μλ₯Ό μ μ νκ³ μμ΅λλ€. λκ°μ λ³μ λͺ¨λ μ΅μ
λ μ΄κΈ° λλ¬Έμ nil
μ΄λΌλ μ΄κΈ°κ°μ κ°μ§κ³ μμ΅λλ€.
var jinha: Person?
var unit4A: Apartment?
μ΄μ νΉμ Person
μΈμ€ν΄μ€μ Apartment
μΈμ€ν΄μ€λ₯Ό μμ± ν μ μκ³ μ΄ μΈμ€ν΄μ€λ€μ jinha
μ unit4A
μ ν λΉ ν μ μμ΅λλ€.
jinha = Person(name: "Jinha Park")
unit4A = Apartment(unit: "4A")
λ μΈμ€ν΄μ€λ€μ μμ±νκ³ ν λΉ ν λ€μ κ°ν μ°Έμ‘°κ° μ΄λ»κ² λ³΄μ¬ μ§λμ§ μ¬κΈ° μμ΅λλ€. jinha
λ³μλ μ΄μ Person
μΈμ€ν΄μ€μ κ°ν μ°Έμ‘°λ₯Ό κ°μ§κ³ μκ³ , unit4A
λ³μλ Apartment
μΈμ€ν΄μ€μ κ°ν μ°Έμ‘°λ₯Ό κ°μ§κ³ μμ΅λλ€.
μ΄μ μ¬λμ΄ μννΈλ₯Ό κ°λλ‘, λκ°μ μΈμ€ν΄μ€λ₯Ό μ°κ²° μν¬ μ μμ΅λλ€. κ·Έλ¦¬κ³ μννΈλ μΈμ
μλ₯Ό κ°μ§κ³ μμ΅λλ€. λλν(!)κ° μ΄ μΈμ€ν΄μ€λ€μ νλ‘νΌν°κ° μΈν
λ μ μλλ‘ jinha
μ unit4A
μ΅μ
λ λ³μμ μ μ₯λμ΄ μλ μΈμ€ν΄μ€λ₯Ό μΈλννκ³ μ κ·Ό νκΈ° μν΄ μ¬μ© λκ³ μλ κ²μ μ£Όλͺ©νμΈμ.
jinha!.apartment = unit4A
unit4A!.tenant = jinha
μ¬κΈ°μ λκ°μ μΈμ€ν΄μ€κ° κ°μ΄ μ°κ²° λ ν κ°ν μν μ°Έμ‘°κ° μ΄λ»κ² 보μ΄λμ§κ° μμ΅λλ€.
λΆννλ, λ μΈμ€ν΄μ€λ₯Ό μ°κ²° νλ κ²μ κ·Έκ²λ€ μ¬μ΄μ κ°ν μν μ°Έμ‘°λ₯Ό λ§λλλ€. Person
μΈμ€ν΄μ€λ μ΄μ Apartment
μΈμ€ν΄μ€μ κ°ν μ°Έμ‘°λ₯Ό κ°μ§κ³ μκ³ , Apartment
μΈμ€ν΄μ€λ Person
μΈμ€ν΄μ€μ κ°ν μ°Έμ‘°λ₯Ό κ°μ§κ³ μμ΅λλ€. λ°λΌμ, jinha
μ unit4A
λ³μλ€μ μ°κ²° λ κ°ν¨ μ°Έμ‘°λ₯Ό κΉ° λ, μ°Έμ‘° κ°μκ° 0μΌλ‘ λ¨μ΄μ§μ§ μμ κ²μ΄κ³ , ARCμ μν΄ μΈμ€ν΄μ€κ° ν΄μ λμ§ μμ κ² μ
λλ€.
jinha = nil
unit4A = nil
μ΄ λ³μλ€μ nil
μ λμ
ν΄λ μλ©Έμ λν νΈμΆ λμ§ μλ κ²μ μ μνμΈμ. κ°ν μ°Έμ‘° μνμ μ±μ λ©λͺ¨λ¦¬ λμλ₯Ό λ°μμν€λ©°, Person
κ³Ό Apartment
μΈμ€ν΄μ€κ° ν΄μ λλ κ²μ λ§μ΅λλ€.
μ΄κ²μ΄ jinha
μ unit4A
λ³μμ nil
μ λμ
ν ν κ°ν μν μ°Έμ‘°μ λͺ¨μ΅μ
λλ€.
Person
μΈμ€ν΄μ€μ Apartment
μΈμ€ν΄μ€ μ¬μ΄μ κ°ν μ°Έμ‘°λ μ μ§λκ³ μμ΄μ§μ§ μμ΅λλ€.
ν΄λμ€ μΈμ€ν΄μ€ κ°μ κ°ν μν μ°Έμ‘° ν΄κ²°νκΈ°(Resolving Strong Refernce Cycles Between Class Instances)
Swift ν΄λμ€ νμ μ νλ‘νΌν°μ κ΄λ ¨ν΄μ κ°ν μν μ°Έμ‘°λ₯Ό ν΄κ²°νκΈ° μν weakμ°Έμ‘°μ unownedμ°Έμ‘° λκ°μ§ λ°©λ²μ μ 곡ν©λλ€.
weakκ³Ό unowned μ°Έμ‘°λ μν μ°Έμ‘° μμ νλμ μΈμ€ν΄μ€κ° λ€λ₯Έ μΈμ€ν΄μ€λ₯Ό κ°νκ² μ μ§νμ§ μμ μ±λ‘ μ°Έμ‘° ν μ μκ² ν©λλ€. μ΄ μΈμ€ν΄μ€λ κ°ν μν μ°Έμ‘°λ₯Ό λ§λ€μ§ μκ³ μλ‘ μ°Έμ‘° ν μ μμ΅λλ€.
λ€λ₯Έ μΈμ€ν΄μ€κ° λ 짧μ μλͺ
μ£ΌκΈ°λ₯Ό κ°μ§κ³ μμ λ, μ¦ λ€λ₯Έ μΈμ€ν΄μ€κ° λ¨Όμ ν΄μ λ μ μμ λ, weakμ°Έμ‘°λ₯Ό μ¬μ©νμΈμ. μμ Apartment
μμ μμ, μννΈλ μλͺ
μ£ΌκΈ°μ μ΄λ€ μμ μ μννΈμ μΈμ
μκ° μλ κ²μ΄ μ μ νκ³ , κ·Έλμ μ΄ κ²½μ°μ weak μ°Έμ‘°λ κ° μν μ°Έμ‘°λ₯Ό κΉ¨λ μ μ ν λ°©λ² μ
λλ€. λ°λλ‘, unowned μ°Έμ‘°λ λ€λ₯Έ μΈμ€ν΄μ€κ° κ°μ μλͺ
μ£ΌκΈ°λ₯Ό κ°κ±°λ λ κΈ΄ μλͺ
μ£ΌκΈ°λ₯Ό κ°μ§ λ μ¬μ© νμΈμ.