45

I came across a function called deinit() while reading The Swift Programming Language guide, but I'm still wondering why and when we need to implement it since we don't really need to manage memory.

Ayu
  • 926
  • 1
  • 9
  • 15
  • The same ocassions when you would use `dealloc` in obj-c under ARC. – Sulthan Jun 03 '14 at 15:14
  • 1
    Is the deinit in swift as useless as the finalize() in java, or is swift better at predicting when things will be deallocated? – jbruni Mar 04 '20 at 21:03

7 Answers7

45

It's not required that you implement that method, but you can use it if you need to do some action or cleanup before deallocating the object.

The Apple docs include an example:

struct Bank {
    static var coinsInBank = 10_000
    static func vendCoins(var numberOfCoinsToVend: Int) -> Int {
        numberOfCoinsToVend = min(numberOfCoinsToVend, coinsInBank)
        coinsInBank -= numberOfCoinsToVend
        return numberOfCoinsToVend
    }
    static func receiveCoins(coins: Int) {
        coinsInBank += coins
    }
}

class Player {
    var coinsInPurse: Int
    init(coins: Int) {
        coinsInPurse = Bank.vendCoins(coins)
    }
    func winCoins(coins: Int) {
        coinsInPurse += Bank.vendCoins(coins)
    }
    deinit {
        Bank.receiveCoins(coinsInPurse)
    }
}

So whenever the player is removed from the game, its coins are returned to the bank.

Connor Pearson
  • 63,902
  • 28
  • 145
  • 142
  • 1
    How would you go about "removing" a player from the game? I have a car class and if that car crashes it goes to the junkyard, therefore making the overall car population go down. I would like to remove the car from the car population. I have my deinit { Car.population -= 1 } but don't know how to actually deallocate and decrease the population. – Govind Rai Jun 24 '16 at 21:10
  • Any ideas why Apple made a change from struct Bank to class Bank? – user523234 Aug 14 '16 at 08:08
  • 2
    @user523234 Because a bank has a clear identity, there is the one bank you go to where you deposit your money. A bank is not just an abstract concept (a collection of information) and two banks even with the exact same information would not be the same bank. – idmean Jul 14 '17 at 08:13
  • Termination is one thing, but **what about method return or throw**; Is `deinit` called instantly when last obj-ref gets out of scope, or should I again and again use `defer` instead, where ever such behavior is needed? – Top-Master Aug 07 '21 at 22:32
6

A deinit() is called immediately before a class instance is deallocated, and it is helpful when you are working with your own resources. For example, if you create a custom class to open a file and write some data to it, you might need close the file before the class instance is deallocated. The most important thing to remember is a class definition can have at most one deinit() per class

cokeman19
  • 2,405
  • 1
  • 25
  • 40
RakeshDipuna
  • 1,570
  • 13
  • 19
4

from iOS9, removeObserver is called automatically.

shtnkgm
  • 1,396
  • 15
  • 17
  • Thx man, this is the docs of it https://developer.apple.com/documentation/foundation/notificationcenter/1413994-removeobserver – Jakfar Shodiq Jul 21 '20 at 04:15
3

If your class manages a file handle or a different resource you can close that handle in deinit to ensure that it doesn't live on after the object has been freed.

lassej
  • 6,256
  • 6
  • 26
  • 34
3

A deinitializer is called immediately before a class instance is deallocated. You write deinitializers with the deinit keyword, similar to how initializers are written with the init keyword. Deinitializers are only available on class types.Class definitions can have at most one deinitializer per class. The deinitializer does not take any parameters and is written without parentheses. I used deinit to removeObserver of notification from the application,as given below.

deinit {
    NotificationCenter.default.removeObserver(self, name: 
    NSNotification.Name(rawValue: "gotoLogin"), object: nil)
    NotificationCenter.default.removeObserver(self, name: 
    NSNotification.Name(rawValue: "gotoMain"), object: nil)
    NotificationCenter.default.removeObserver(self, name: 
    NSNotification.Name(rawValue: "gotoRegister"), object: 
    nil)
    NotificationCenter.default.removeObserver(self, name: 
    NSNotification.Name(rawValue: "gotoBook"), object: nil)
    NotificationCenter.default.removeObserver(self, name: 
    NSNotification.Name(rawValue: "gotoCurrentMainMenu"), 
    object: nil)
    NotificationCenter.default.removeObserver(self, name: 
    NSNotification.Name(rawValue: "gotoEventMenu"), 
    object: nil)
}
Dipak Dhondge
  • 115
  • 1
  • 9
0

If you are creating much of operations in some object which needs to be deallocated at your pace, you can do that in deinit

0

The "best answer" should now look more like this

I was not able to edit it

 struct Bank {
static var coinsInBank = 10000
static func vendCoins(money numberOfCoinsToVend: Int) -> Int {
    let CoinsToVend = min(numberOfCoinsToVend, coinsInBank)
    coinsInBank -= CoinsToVend
    return CoinsToVend
}
static func receiveCoins(coins: Int) {
    coinsInBank += coins
}
}

class Player {
var coinsInPurse: Int
init(coins: Int) {
    coinsInPurse = Bank.vendCoins(money:coins)
}
func winCoins(coins: Int) {
    coinsInPurse += Bank.vendCoins(money:coins)
}
deinit {
    Bank.receiveCoins(coins:coinsInPurse)
}
}



print("Balance in Account: \(Bank.coinsInBank)")

 var Player1: Player? = Player(coins: 9000)



  print("Requested Amount to Withdraw: \(Player1!.coinsInPurse)")

  print("Balance After Withdraw: \(Bank.coinsInBank)")

 Player1 = nil

 print("Balance in Account: \(Bank.coinsInBank)")

And output should look like this

Balance in Account: 10000 Requested Amount to Withdraw: 9000 Balance After Withdraw: 1000 Balance in Account: 10000

PowerPlay
  • 61
  • 6