following is a code sample you can run in a playground
import Foundation
class TempNotifier {
var onChange: (Int) -> Void = {t in }
var currentTemp = 72
init() {
// 1.
onChange = { [unowned self] temp in
self.currentTemp = temp
}
// 2.
onChange = {[unowned self] temp in
self.tempHandler(temp)
}
// 3.
unowned let s = self
onChange = s.tempHandler
}
deinit {
println("deinit")
}
private func tempHandler(temp: Int) {
self.currentTemp = temp
}
}
var tN: TempNotifier? = TempNotifier()
tN = nil
It illustrates 3 ways of assigning a value to a block with potential retain-cycle. Case 1.
and 2.
create no retain cycle due to unowned self
however in case 3.
it seems like there is no way to break the retain cycle (deinit
is never printed). As you can see, I even tried to create a local unowned reference.
Is this the desired behaviour, is it "by design"? Or am I missing something?
Thanks!
Cross-posted from https://devforums.apple.com/message/1122247
For example; when we set mercedes instance to nil , the compiler cannot decrease its ARC to 1 because a Car object is still referencing the mercedes and vice versa. In order to prevent this retain cycle, we need to declare at least one of the variable as weak or unowned.
The first rule to avoid retain cycles is that an object must never retain its parent. This changes the previous diagram to the following: This is the easy case: an object should never retain its parent when it makes a pointer to the parent. Notice that the term "weak pointer" is used.
Structs and Classes A choice between a struct and a class can cause a retain cycle. Both structs and classes can have constants, variables, functions and protocols.
Take a look at what objects are in-memory and how much of each instance exists per object. Check for these signs of a retain cycle/memory leak: In the left panel do you see any objects/classes/views and etc on the list that should not be there or should have been deallocated?
Yes, this is the designed behavior.
Accessing a method without calling it, like s.tempHandler
, is equivalent to a closure expression like { x in s.tempHandler(x) }
. Here s
is not marked unowned
or weak
, and hence is retained by the closure. If you want it to be captured as unowned
or weak
, you must explicitly write out the closure.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With