Reputation: 5466
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
Upvotes: 5
Views: 1271
Reputation: 122449
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.
Upvotes: 6