dealloc in Swift
Asked Answered
T

6

153

I would like to perform some cleanup at the end of a view controller's life, namely to remove an NSNotificationCenter notification. Implementing dealloc results in a Swift compiler error:

Cannot override 'dealloc' which has been marked unavailable

What is the preferred way to perform some cleanup at the end of an object's life in Swift?

Thoracotomy answered 26/8, 2014 at 4:12 Comment(0)
T
352
deinit {
    // perform the deinitialization
}

From the Swift Documentation:

A deinitializer is called immediately before a class instance is deallocated. You write deinitializers with the deinit keyword, similar to how intializers are written with the init keyword. Deinitializers are only available on class types.

Typically you don’t need to perform manual clean-up when your instances are deallocated. However, when you are working with your own resources, you might need to perform some additional clean-up yourself. For example, if you create a custom class to open a file and write some data to it, you might need to close the file before the class instance is deallocated.

Thoracotomy answered 26/8, 2014 at 4:12 Comment(0)
V
50
deinit {
    // perform the deinitialization
}

is the correct answer for Swift "dealloc".

However, it is good to point out new in iOS 9 that NSNotificationCenter no longer needs to be cleaned up!

https://developer.apple.com/library/content/releasenotes/Foundation/RN-FoundationOlderNotes/index.html#X10_11Notes

NSNotificationCenter

In OS X 10.11 and iOS 9.0 NSNotificationCenter and NSDistributedNotificationCenter will no longer send notifications to registered observers that may be deallocated. If the observer is able to be stored as a zeroing-weak reference the underlying storage will store the observer as a zeroing weak reference, alternatively if the object cannot be stored weakly (i.e. it has a custom retain/release mechanism that would prevent the runtime from being able to store the object weakly) it will store the object as a non-weak zeroing reference. This means that observers are not required to un-register in their deallocation method. The next notification that would be routed to that observer will detect the zeroed reference and automatically un-register the observer. If an object can be weakly referenced notifications will no longer be sent to the observer during deallocation; the previous behavior of receiving notifications during dealloc is still present in the case of non-weakly zeroing reference observers. Block based observers via the -[NSNotificationCenter addObserverForName:object:queue:usingBlock] method still need to be un-registered when no longer in use since the system still holds a strong reference to these observers. Removing observers (either weakly referenced or zeroing referenced) prematurely is still supported. CFNotificationCenterAddObserver does not conform to this behavior since the observer may not be an object.

but note the points below about strong references, so you may have to worry about cleanup anyway...?

Von answered 7/11, 2015 at 21:55 Comment(4)
Unless the notification block has a strong reference, then you must remove the observer.Hardcastle
+1 for not having to clean up observers. Important to know! I make all capturing references weak so never have to deal with this.Quillon
Notification blocks always seem to be strongly referenced according to the documentation. So: If you are using blocks to handle your notifications you have to unregister for them inside deinit.Glare
unless all strong reference removed the deinit won't get called, hence always check when view controller goes out of scope or removed from navigation stack deinit should get called. To check that there is no memory leak you can use Profile option from Xcode which can easily log memory leaks. Hope this clears the point.Suet
H
26

https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/Deinitialization.html

Swift automatically deallocates your instances when they are no longer needed, to free up resources. Swift handles the memory management of instances through automatic reference counting (ARC), as described in Automatic Reference Counting. Typically you don’t need to perform manual clean-up when your instances are deallocated. However, when you are working with your own resources, you might need to perform some additional clean-up yourself. For example, if you create a custom class to open a file and write some data to it, you might need to close the file before the class instance is deallocated.

Class definitions can have at most one deinitializer per class. The deinitializer does not take any parameters and is written without parentheses:

deinit {
    // perform the deinitialization
}
Hellgrammite answered 26/8, 2014 at 5:29 Comment(0)
A
3

removing observer is required before deallocation otherwise crash would happen. It can be done using

deinit {
    // perform the deinitialization
    print("deinit")

    removeObserver(self, forKeyPath: kSelectedViewControllerKey, context: nil)
    removeObserver(self, forKeyPath: kSelectedIndexKey, context: nil)

}
Ashworth answered 30/9, 2018 at 7:9 Comment(0)
S
0

If you really want to remove something when view goes out of scope and start when in scope, I would suggest let's do it in the controller's didAppear and didDisappear method. Even NSNotificationCenter also can remove and added back when the view appears/disappear.

Suet answered 12/10, 2020 at 11:16 Comment(0)
E
-2

Be careful when calling a method in other class from deinit it will probably end up in crash

Ehlke answered 29/1, 2018 at 11:53 Comment(1)
Downvoted as that should not be necessarily the case. From ref. docs: Because an instance is not deallocated until after its deinitializer is called, a deinitializer can access all properties of the instance it is called on and can modify its behavior based on those properties (such as looking up the name of a file that needs to be closed).Downhill

© 2022 - 2024 — McMap. All rights reserved.