In the following code NSString
and NSNumber
are not de-initialised when the reference is removed . NSMutableString
and NSAttributedString
are de-initialised . What is the criteria for deinit ?
class WeakHolder<R : AnyObject> {
weak var cheez : R?
init(_ _cheez : R) {
cheez = _cheez
}
}
do {
var nsStringCollection = [NSString(string: "77"),NSString(string: "99")]
let weakNSStringHolder = WeakHolder(nsStringCollection[1])
nsStringCollection.removeLast()
print("NSString : \(weakNSStringHolder.cheez)")
}
do {
var nsMutableStringCollection = [NSMutableString(string: "77_m"),NSMutableString(string: "99_m")]
let weakNSMutableStringHolder = WeakHolder(nsMutableStringCollection[1])
nsMutableStringCollection.removeLast()
print("NSMutableString : \(weakNSMutableStringHolder.cheez)")
}
do {
var nsNumberCollection = [NSNumber(integerLiteral: 77),NSNumber(integerLiteral: 99)]
let weakNumberHolder = WeakHolder(nsNumberCollection[1])
nsNumberCollection.removeLast()
print("Number : \(weakNumberHolder.cheez)")
}
do {
var nsAttributedCollection = [NSAttributedString(string: "77_atts"),NSAttributedString(string: "99_atts")]
let weakAttributedHolder = WeakHolder(nsAttributedCollection[1])
nsAttributedCollection.removeLast()
print("AttrString : \(weakAttributedHolder.cheez)")
}
Output :
NSString : Optional(99)
NSMutableString : nil
Number : Optional(99)
AttrString : nil
Short NSString
objects are stored directly in their (tagged) pointer, and do not require memory management. Other static strings are stored in the binary and may never be deallocated. Neither allocate memory, so neither must release it.
NSMutableString
and NSAttributedString
allocate actual objects, so they also need to deallocate them.
Both behaviors are implementation details and you should not rely on them. They are not promised.
The rule for memory management is to hold a strong reference to anything you care about, and remove your strong reference when you no longer care about it. deinit
should only cleanup memory (calling free
on malloc-blocks, for example, if needed). No "business logic" should be in a deinit
; there's no promise it will ever run. (For example, during normal program termination, deinit
is skipped, unlike in C++.)