โŒจ๏ธ Language/swift

[Swift] ์ž๋™ ์ฐธ์กฐ ์นด์šดํŠธ

hyebin (Helia) 2024. 4. 2. 09:11
๋ฐ˜์‘ํ˜•

์ž๋™ ์ฐธ์กฐ ์นด์šดํŠธ(ARC, Automatic Reference Counting)

  • ์•ฑ์˜ ๋ฉ”๋ชจ๋ฆฌ ๊ด€๋ฆฌ๋ฅผ ์œ„ํ•ด ์‚ฌ์šฉ
  • ์ž๋™์œผ๋กœ ์ฐธ์กฐ ํšŸ์ˆ˜๋ฅผ ๊ด€๋ฆฌํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๋Œ€๋ถ€๋ถ„์˜ ๊ฒฝ์šฐ์— ๋ฉ”๋ชจ๋ฆฌ ๊ด€๋ฆฌ์— ์‹ ๊ฒฝ์“ธ ํ•„์š”๊ฐ€ ์—†๊ณ  ARC๊ฐ€ ์ž๋™์œผ๋กœ ์‚ฌ์šฉํ•˜์ง€ ์•Š๋Š” ์ธ์Šคํ„ด์Šค๋ฅผ ๋ฉ”๋ชจ๋ฆฌ์—์„œ ํ•ด์ง€
  • ํŠน์ • ๊ฒฝ์šฐ์— ARC์—์„œ ๋ฉ”๋ชจ๋ฆฌ ๊ด€๋ฆฌ๋ฅผ ์œ„ํ•ด ์ฝ”๋“œ์˜ ํŠน์ • ๊ด€๊ณ„์— ๋Œ€ํ•œ ์ •๋ณด๋ฅผ ํ•„์š”๋กœ ํ•จ
  • ์ฐธ์กฐ ํšŸ์ˆ˜๋Š” ํด๋ž˜์Šค ํƒ€์ž…์˜ ์ธ์Šคํ„ด์Šค์—๋งŒ ์ ์šฉ๋˜๊ณ  ๊ตฌ์กฐ์ฒด, ์—ด๊ฑฐํ˜• ๋“ฑ ๊ฐ’ ํƒ€์ž…์—๋Š” ์ ์šฉ๋˜์ง€ ์•Š์Œ

 

ARC ๋™์ž‘

  • ์ƒˆ๋กœ์šด ํด๋ž˜์Šค ์ธ์Šคํ„ด์Šค๋ฅผ ๋งŒ๋“ค ๋•Œ ๋งˆ๋‹ค ARC๋Š” ์ธ์Šคํ„ด์Šค ์ •๋ณด๋ฅผ ๋‹ด๋Š”๋ฐ ํ•„์š”ํ•œ ํฌ๊ธฐ์˜ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ํ• ๋‹น
  • ๋ฉ”๋ชจ๋ฆฌ๋Š” ์ธ์Šคํ„ด์Šค์— ๋Œ€ํ•œ ์ •๋ณด์™€ ๊ด€๋ จ๋œ ์ €์žฅ ํ”„๋กœํผํ‹ฐ ๊ฐ’์„ ๊ฐ–๊ณ  ์žˆ์Œ
  • ์ธ์Šคํ„ด์Šค๊ฐ€ ๋”์ด์ƒ ์‚ฌ์šฉ๋˜์ง€ ์•Š์„ ๋•Œ ARC๋Š” ๊ทธ ์ธ์Šคํ„ด์Šค๊ฐ€ ์ฐจ์ง€ํ•˜๊ณ  ์žˆ๋Š” ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ํ•ด์ง€ํ•ด ๊ณต๊ฐ„์„ ํ™•๋ณด
  • ARC๋Š” ์•„์ง ์‚ฌ์šฉ์ค‘์ธ ์ธ์Šคํ„ด์Šค๋ฅผ ํ•ด์ง€ํ•˜์ง€ ์•Š๊ธฐ ์œ„ํ•ด ํ•˜๋‚˜๋ผ๋„ ์ฐธ์กฐ๊ฐ€ ์žˆ๋Š” ๊ฒฝ์šฐ ๋ฉ”๋ชจ๋ฆฌ์—์„œ ํ•ด์ง€ํ•˜์ง€ ์•Š์Œ

 

ARC ์‚ฌ์šฉ

class Person {
    let name: String
    init(name: String) {
        self.name = name
        print("\\(name) is being initialized")
    }
    deinit {
        print("\\(name) is being deinitialized")
    }
}

var reference1: Person?
var reference2: Person?
var reference3: Person?

reference1 = Person(name: "John Appleseed")
// Prints "John Appleseed is being initialized"

reference2 = reference1
reference3 = reference1

ํ˜„์žฌ Person ์ธ์Šคํ„ด์Šค์— ๋Œ€ํ•œ ์ฐธ์กฐ ํšŸ์ˆ˜๋Š” 3

reference1 = nil
reference2 = nil

ํ˜„์žฌ Person ์ธ์Šคํ„ด์Šค์— ๋Œ€ํ•œ ์ฐธ์กฐ ํšŸ์ˆ˜๋Š” 1

reference3 = nil
// Prints "John Appleseed is being deinitialized"

Person์ธ์Šคํ„ด์Šค๋ฅผ ์ฐธ์กฐํ•˜๊ณ ์žˆ๋Š” ๊ฒƒ์ด ์—†์œผ๋ฏ€๋กœ ARC๊ฐ€ Person ์ธ์Šคํ„ด์Šค๋ฅผ ๋ฉ”๋ชจ๋ฆฌ์—์„œ ํ•ด์ง€

 

ํด๋ž˜์Šค ์ธ์Šคํ„ด์Šค๊ฐ„ ๊ฐ•ํ•œ ์ฐธ์กฐ ์ˆœํ™˜

ํด๋ž˜์Šค์˜ ์ธ์Šคํ„ด์Šค๊ฐ„ ๊ฐ•ํ•˜๊ฒŒ ์ƒํ˜ธ์ฐธ์กฐํ•˜๊ณ  ์žˆ๋Š” ๊ฒฝ์šฐ ๋ฉ”๋ชจ๋ฆฌ์—์„œ ํ•ด์ œ๋˜์ง€ ์•Š์Œ

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") }
}

var john = Person(name: "John Appleseed")
var unit4A = Apartment(unit: "4A")

john!.apartment = unit4A
unit4A!.tenant = john

 

๋‘ ๊ฐœ์˜ ํด๋ž˜์Šค๊ฐ€ ์„œ๋กœ ์ธ์Šคํ„ด์Šค๋ฅผ ์†Œ์œ ํ•˜๊ณ  ์žˆ๋Š”๊ฒฝ์šฐ ์„œ๋กœ๋ฅผ ์ฐธ์กฐํ•˜๊ฒŒ๋˜๊ณ , nil์„ ํ• ๋‹นํ•ด ํƒ์กฐ๊ฐ€ ํ•ด์ง€ํ•˜๋ ค๊ณ  ํ•˜๋”๋ผ๋„ ๋‘ ์ธ์Šคํ„ด์Šค๋Š” ํ•ด์ง€๋˜์ง€ ์•Š์Œ

๋ฉ”๋ชจ๋ฆฌ ๋ˆ„์ˆ˜ ๋ฐœ์ƒ

 

๊ฐ•ํ•œ ์ฐธ์กฐ ์ˆœํ™˜ ๋ฌธ์ œ ํ•ด๊ฒฐ

์•ฝํ•œ ์ฐธ์กฐ

์•ฝํ•œ ์ฐธ์กฐ๋กœ ์„ ์–ธํ•˜๋ฉด ์ฐธ์กฐํ•˜๊ณ  ์žˆ๋Š” ๊ฒƒ์ด ๋จผ์ € ๋ฉ”๋ชจ๋ฆฌ์—์„œ ํ•ด์ง€๋˜๊ธฐ ๋•Œ๋ฌธ์— ๋Ÿฐํƒ€์ž„์— ์ž๋™์œผ๋กœ ์ฐธ์กฐํ•˜๊ณ  ์žˆ๋Š” ๋ณ€์ˆ˜์— nil ํ• ๋‹น

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 }
    weak var tenant: Person?
    deinit { print("Apartment \\(unit) is being deinitialized") }
}

var john: Person?
var unit4A: Apartment?

john = Person(name: "John Appleseed")
unit4A = Apartment(unit: "4A")

john!.apartment = unit4A
unit4A!.tenant = john

john = nil
// Prints "John Appleseed is being deinitialized"

unit4A = nil
// Prints "Apartment 4A is being deinitialized"

๋ฏธ์†Œ์œ  ์ฐธ์กฐ

์ฐธ์กฐ ๋Œ€์ƒ์ด ๋˜๋Š” ์ธ์Šคํ„ด์Šค๊ฐ€ ํ˜„์žฌ ์ฐธ์กฐํ•˜๊ณ ์žˆ๋Š” ๊ฒƒ๊ณผ ๊ฐ™์€ ์ƒ์• ์ฃผ๊ธฐ๋ฅผ ๊ฐ–๊ฑฐ๋‚˜ ๋” ๊ธด ์ƒ์• ์ฃผ๊ธฐ๋ฅผ ๊ฐ–๊ธฐ ๋•Œ๋ฌธ์— ํ•ญ์ƒ ์ฐธ์กฐ์— ๊ทธ ๊ฐ’์ด ์žˆ๋‹ค๊ณ  ๊ธฐ๋Œ€๋จ

๋”ฐ๋ผ์„œ ARC๋Š” ๋ฏธ์†Œ์œ  ์ฐธ์กฐ์—๋Š” ์ ˆ๋Œ€ nil์„ ํ• ๋‹นํ•˜์ง€ ์•Š์Œ <์˜ต์…”๋„ ํƒ€์ž… ์‚ฌ์šฉํ•˜์ง€ ์•Š์Œ>

class Customer {
    let name: String
    var card: CreditCard?
    init(name: String) {
        self.name = name
    }
    deinit { print("\\(name) is being deinitialized") }
}

class CreditCard {
    let number: UInt64
    unowned let customer: Customer
    init(number: UInt64, customer: Customer) {
        self.number = number
        self.customer = customer
    }
    deinit { print("Card #\\(number) is being deinitialized") }
}

var john: Customer?

john = Customer(name: "John Appleseed")
john!.card = CreditCard(number: 1234_5678_9012_3456, customer: john!)

john = nil
// Prints "John Appleseed is being deinitialized"
// Prints "Card #1234567890123456 is being deinitialized"

 

๋ฏธ์†Œ์œ  ์ฐธ์กฐ์™€ ์•”์‹œ์  ์˜ต์…”๋„ ํ”„๋กœํผํ‹ฐ ์–ธ๋ž˜ํ•‘

๋‘ ํ”„๋กœํผํ‹ฐ๊ฐ€ ํ•ญ์ƒ ๊ฐ’์„ ๊ฐ–์ง€๋งŒ ํ•œ๋ฒˆ ์ดˆ๊ธฐํ™” ๋˜๋ฉด ์ ˆ๋Œ€ nil์ด ๋˜์ง€ ์•Š๋Š” ๊ฒฝ์šฐ ๋ฏธ์†Œ์œ  ํ”„๋กœํผํ‹ฐ๋ฅผ ์•”์‹œ์  ์˜ต์…”๋„ ํ”„๋กœํผํ‹ฐ ์–ธ๋ž˜ํ•‘์„ ์‚ฌ์šฉํ•ด ์ฐธ์กฐ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐ

class Country {
    let name: String
    var capitalCity: City!
    init(name: String, capitalName: String) {
        self.name = name
        self.capitalCity = City(name: capitalName, country: self)
    }
}

class City {
    let name: String
    unowned let country: Country
    init(name: String, country: Country) {
        self.name = name
        self.country = country
    }
}

var country = Country(name: "Canada", capitalName: "Ottawa")
print("\\(country.name)'s capital city is called \\(country.capitalCity.name)")
// Prints "Canada's capital city is called Ottawa"

 

ํด๋กœ์ €์—์„œ์˜ ๊ฐ•ํ•œ ์ฐธ์กฐ ์ˆœํ™˜

ํด๋กœ์ €์—์„œ๋Š” self๋ฅผ ์บก์ณํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๊ฐ•ํ•œ ์ฐธ์กฐ ์ˆœํ™˜์ด ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ์Œ

ํด๋กœ์ €์—์„œ ๊ฐ•ํ•œ ์ฐธ์กฐ ์ˆœํ™˜ ๋ฌธ์ œ ํ•ด๊ฒฐ

์บก์ณ ์ฐธ์กฐ์— ๊ฐ•ํ•œ ์ฐธ์กฐ ๋Œ€์‹  ์•ฝํ•œ ์ฐธ์กฐ ํ˜น์€ ๋ฏธ์†Œ์œ  ์ฐธ์กฐ ์ง€์ • ๊ฐ€๋Šฅ

 

์บก์ณ๋ฆฌ์ŠคํŠธ ์ •์˜

ํด๋กœ์ €์˜ ํŒŒ๋ผ๋ฏธํ„ฐ ์•ž์— ์†Œ๊ด„ํ˜ธ๋ฅผ ๋„ฃ๊ณ  ๊ทธ ์•ˆ์— ๊ฐ ์บก์ณ ๋Œ€์ƒ์— ๋Œ€ํ•œ ์ฐธ์กฐ ํƒ€์ž„์„ ์ ์Œ

lazy var someClosure: (Int, String) -> String = {
    [unowned self, weak delegate = self.delegate!] (index: Int, stringToProcess: String) -> String in
    // closure body goes here
}
๋ฐ˜์‘ํ˜•