1. Deinitializer on Class Types πŸ‘©β€πŸ’»

DeinitializerλŠ” class instance 의 할당이 ν•΄μ œ(deallocate)되기 직전에 호좜되며, deinit keyword λ₯Ό μ΄μš©ν•΄ μž‘μ„±ν•œλ‹€. DeinitializerλŠ” class νƒ€μž…μ—μ„œλ§Œ μ‚¬μš©λ  수 μžˆλ‹€.

일반 μ½”λ“œ λΈ”λŸ­μ„ νƒˆμΆœν•˜κΈ° 직전에 ν˜ΈμΆœλ˜λŠ” μ½”λ“œλŠ” defer keyword λ₯Ό μ‚¬μš©ν•΄ μ •μ˜ν•œλ‹€.


2. How Deinitialization Works πŸ‘©β€πŸ’»

Swift λŠ” λ¦¬μ†ŒμŠ€ 확보λ₯Ό μœ„ν•΄ μžλ™μœΌλ‘œ 더 이상 ν•„μš”ν•˜μ§€ μ•Šμ€ instancesλ₯Ό deallocateν•œλ‹€. 이λ₯Ό μœ„ν•΄ Swift λŠ” ARC(Automatic Reference Counting)λ₯Ό μ΄μš©ν•΄ instances 의 λ©”λͺ¨λ¦¬λ₯Ό κ΄€λ¦¬ν•œλ‹€.

일반적으둜 instances 의 deallocate λ₯Ό μˆ˜λ™μœΌλ‘œ ν•  ν•„μš”λŠ” μ—†λ‹€. ν•˜μ§€λ§Œ 자기 μžμ‹ μ˜ λ¦¬μ†ŒμŠ€λ₯Ό μ΄μš©ν•˜λŠ” 경우 직접 cleanup 을 μˆ˜ν–‰ν•΄μ€˜μ•Όν•œλ‹€. 예λ₯Ό λ“€μ–΄, νŒŒμΌμ„ μ—΄κ³  데이터λ₯Ό μ“°κΈ° μœ„ν•΄ custom classλ₯Ό μƒμ„±ν•˜λŠ” 경우 class instance κ°€ deallocated 되기 μ „ λ°˜λ“œμ‹œ νŒŒμΌμ„ λ‹«μ•„ λ¦¬μ†ŒμŠ€λ₯Ό μ •λ¦¬ν•΄μ•Όν•œλ‹€.


Syntax

deinit {
    // perform the deinitialization
}

Deinitializer λŠ” Class 에 ν•˜λ‚˜λ§Œ μ‘΄μž¬ν•˜λ©°, νŒŒλΌλ―Έν„°κ°€ μ‘΄μž¬ν•˜μ§€ μ•ŠμœΌλ―€λ‘œ, λ³„λ„μ˜ κ΄„ν˜Έ 없이 μž‘μ„±ν•œλ‹€.
Deinitializer λŠ” instance κ°€ deallocation 되기 μ „ μžλ™μœΌλ‘œ 호좜되며, λͺ…μ‹œμ μœΌλ‘œ ν˜ΈμΆœν•  수 μ—†λ‹€.

Superclasses 의 Deinitializer λŠ” Subclasses 에 μƒμ†λ˜λ©°, Superclasses 의 Deinitializer λŠ” Subclasses 의 Deinitializer 의 λ§ˆμ§€λ§‰μ— μžλ™μœΌλ‘œ ν˜ΈμΆœλœλ‹€. Superclasses 의 Deinitializer λŠ” Subclasses κ°€ μžμ‹ μ˜ Deinitializer λ₯Ό μ œκ³΅ν•˜μ§€ μ•Šλ”λΌλ„ 항상 ν˜ΈμΆœλœλ‹€.

Class Instance λŠ” Deinitializer κ°€ 호좜되기 μ „κΉŒμ§€ deallocated λ˜μ§€ μ•ŠκΈ° λ•Œλ¬Έμ—, Deinitializer λŠ” instance 의 λͺ¨λ“  Properties 에 μ ‘κ·Ό 및 μˆ˜μ •ν•  수 μžˆλ‹€.


3. Deinitializers in Action πŸ‘©β€πŸ’»

Bank 와 Player classes λ₯Ό μ΄μš©ν•œ κ²Œμž„μ„ 톡해 Deinitializers λ₯Ό μ΄ν•΄ν•˜λ„λ‘ ν•˜μž.

1. Bank class

Back class λŠ” μœ ν†΅μ€‘μΈ 코인이 10,000 개λ₯Ό λ„˜μ§€ μ•Šλ„λ‘ μ‘°μ ˆν•œλ‹€. κ²Œμž„μ—μ„œ ν•˜λ‚˜μ˜ Bank 만 μ‘΄μž¬ν•  수 있기 λ•Œλ¬Έμ—, Bank λŠ” Class 둜 κ΅¬ν˜„λ˜λ©°, 코인을 κ΄€λ¦¬ν•˜κΈ° μœ„ν•œ properties 와 methods λ₯Ό κ°–λŠ”λ‹€.

Bank λŠ” coinsInBank property λ₯Ό μ΄μš©ν•΄ ν˜„μž¬ μœ ν†΅μ€‘μΈ μ½”μΈμ˜ 개수λ₯Ό μΆ”μ ν•œλ‹€.
λ˜ν•œ μ½”μΈμ˜ 뢄배와 μˆ˜μ§‘μ„ μ²˜λ¦¬ν•˜κΈ° μœ„ν•΄ 2개의 methods distribute(coins:)와 receive(coins:)λ₯Ό μ œκ³΅ν•œλ‹€. distribute(coins:)λŠ” 코인을 λΆ„λ°°ν•˜κΈ° μ „ 은행에 남은 μ½”μΈμ˜ 수λ₯Ό 검사해 은행 μž”κ³ λ³΄λ‹€ λ§Žμ€ 코인을 μš”κ΅¬ν•  경우, λΆ„λ°° κ°€λŠ₯ν•œ 남은 코인 만큼만 λΆ„λ°°ν•œλ‹€.

class Bank {
    static var coinsInBank = 10_000
    static func distribute(coins numberOfCoinsRequested: Int) -> Int {
        let numberOfCoinsToVend = min(numberOfCoinsRequested, coinsInBank)
        coinsInBank -= numberOfCoinsToVend
        return numberOfCoinsToVend
    }
    static func receive(coins: Int) {
        coinsInBank += coins
    }
}

2. Player class

Player class λŠ” μ§€κ°‘μ˜ 코인을 κ΄€λ¦¬ν•˜κΈ° μœ„ν•œ coinsInPurse property λ₯Ό 가지고 있으며, μ΄ˆκΈ°ν™” ν•  λ•Œ Bank λ‘œλΆ€ν„° μΌμ •λŸ‰μ˜ 코인을 λΆ„λ°° λ°›λŠ”λ‹€. Player λŠ” win(coins:) methods λ₯Ό 톡해 μ€ν–‰μœΌλ‘œλΆ€ν„° 코인을 νšλ“ν•˜κ³ , κ²Œμž„μ„ κ·Έλ§Œλ‘˜ λ•Œ Deinitializer λ₯Ό 톡해 μ†Œμœ ν•œ λͺ¨λ“  코인을 은행에 λ°˜ν™˜ν•œλ‹€.

class Player {
    var coinsInPurse: Int
    init(coins: Int) {
        coinsInPurse = Bank.distribute(coins: coins)
    }
    func win(coins: Int) {
        coinsInPurse += Bank.distribute(coins: coins)
    }
    deinit {
        Bank.receive(coins: coinsInPurse)
    }
}

3. Play Game and Deinitializers in Action

ν”Œλ ˆμ΄μ–΄λŠ” μ–Έμ œλ“  κ²Œμž„μ„ λ– λ‚  수 있기 λ•Œλ¬Έμ— Optional둜 μ„ μ–Έν•˜κ³ , ? λ˜λŠ” !λ₯Ό λΆ™μ—¬ μ ‘κ·Όν•œλ‹€.

var playerOne: Player? = Player(coins: 100)
print("A new player has joined the game with \(playerOne!.coinsInPurse) coins")
print("There are now \(Bank.coinsInBank) coins left in the bank")
A new player has joined the game with 100 coins
There are now 9900 coins left in the bank


playerOne?.win(coins: 2_000)
print("A new player has joined the game with \(playerOne?.coinsInPurse ?? 0) coins")
print("There are now \(Bank.coinsInBank) coins left in the bank")
A new player has joined the game with 2100 coins
There are now 7900 coins left in the bank


그리고 ν”Œλ ˆμ΄μ–΄κ°€ μΆ”κ°€λ‘œ κ²Œμž„μ— μ°Έκ°€ν–ˆλ‹€.

var playerTwo: Player? = Player(coins: 1000)
print("PlayerOne has joined the game with \(playerOne!.coinsInPurse) coins")
print("PlayerTwo has joined the game with \(playerTwo!.coinsInPurse) coins")
print("There are now \(Bank.coinsInBank) coins left in the bank")
PlayerOne has joined the game with 2100 coins
PlayerTwo has joined the game with 1000 coins
There are now 6900 coins left in the bank


playerOne 이 κ²Œμž„μ„ λ– λ‚œλ‹€.

playerOne = nil
if playerOne != nil {
    print("PlayerOne has joined the game with \(playerOne!.coinsInPurse) coins")
} else {
    print("PlayerOne has left the game")
}
if playerTwo != nil {
    print("PlayerTwo has joined the game with \(playerTwo!.coinsInPurse) coins")
} else {
    print("PlayerTwo has left the game")
}
print("There are now \(Bank.coinsInBank) coins left in the bank")
PlayerOne has left the game
PlayerTwo has joined the game with 1000 coins
There are now 9000 coins left in the bank

ν”Œλ ˆμ΄μ–΄κ°€ κ²Œμž„μ„ λ– λ‚˜λŠ” ν–‰μœ„λŠ” Optional playerOne λ³€μˆ˜μ— 'nil' 을 ν• λ‹Ήν•˜λŠ” κ²ƒμœΌλ‘œ 이루어진닀.
playerOne 에 nil을 ν• λ‹Ήν•œλ‹€λŠ” 것은 no Player instance λ₯Ό μ˜λ―Έν•˜λ©°, Player instance 에 λŒ€ν•œ playerOne λ³€μˆ˜μ˜ 'reference'κ°€ 깨진닀.

μ•„λ¬΄λŸ° Properties λ˜λŠ” Variables 도 Player instance λ₯Ό μ°Έμ‘°ν•˜μ§€ μ•ŠλŠ”λ‹€λ©΄, λ©”λͺ¨λ¦¬ λ¦¬μ†ŒμŠ€ 확보λ₯Ό μœ„ν•΄ instance 에 λŒ€ν•œ μ°Έμ‘° 할당이 ν•΄μ œλœλ‹€(it’s deallocated in order to free up its memory).

μ΄λŸ¬ν•œ 일이 λ°œμƒλ˜κΈ° 직전, Deinitializer κ°€ μžλ™μœΌλ‘œ 호좜되며, μ •μ˜ν•œλŒ€λ‘œ μ†Œμœ ν•œ λͺ¨λ“  코인을 은행에 λ°˜ν™˜ν•œλ‹€.


playerTwo = nil
if playerOne != nil {
    print("PlayerOne has joined the game with \(playerOne!.coinsInPurse) coins")
} else {
    print("PlayerOne has left the game")
}
if playerTwo != nil {
    print("PlayerTwo has joined the game with \(playerTwo!.coinsInPurse) coins")
} else {
    print("PlayerTwo has left the game")
}
print("There are now \(Bank.coinsInBank) coins left in the bank")
PlayerOne has left the game
PlayerTwo has left the game
There are now 10000 coins left in the bank

playerTwo μ—­μ‹œ κ²Œμž„μ„ λ– λ‚˜λ©° Deinitializer κ°€ 호좜됨으둜 은행에 λͺ¨λ“  코인이 λ°˜ν™˜λœλ‹€.




Reference

  1. β€œDeinitialization.” The Swift Programming Language Swift 5.7. accessed Dec. 19, 2022, Swift Docs Chapter 14 - Deinitialization.