5

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

Sash Zats
  • 5,376
  • 2
  • 28
  • 42
  • In playground deinit() will not be called as variables are always in the scope. I asked similar question here http://stackoverflow.com/questions/29329334/swift-callback-between-classes-using-function-objects-and-strong-reference. But there seems to be no way to achieve it. – Abdullah Apr 07 '15 at 07:19
  • Actually, if you comment out 3. deinit will be called, as for memory management, I am assigning nil to the variable explicitly - that's what causes it to deinit if there are no retain cycles – Sash Zats Apr 07 '15 at 13:56

1 Answers1

6

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.

newacct
  • 119,665
  • 29
  • 163
  • 224