1

In the Swift Book it says the closure needs a capture list when the closure is saved in the object as a property. (using Swift 1.2 in a Playground).

A strong reference cycle can also occur if you assign a closure to a property of a class instance, and the body of that closure captures the instance. This capture might occur because the closure’s body accesses a property of the instance, such as self.someProperty, or because the closure calls a method on the instance, such as self.someMethod(). In either case, these accesses cause the closure to “capture” self, creating a strong reference cycle.

https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/AutomaticReferenceCounting.html

However in this code, I am not storing the closure in the object. Yet it appears I need to put the [unowned self] otherwise deinit is never called.

class NamedObject {

    var name: String

    init(name: String) {
        self.name = name
    }

    func update() {
        dispatch_async(dispatch_get_main_queue()) { // [unowned self] in // capture list...uncomment to get deinit to call.     
            self.name = "foo"
        }
    }

    deinit {
        println("\(name) is being deinitialized")
    }
}

var hello : NamedObject? = NamedObject(name: "hello")
hello?.name
hello?.update()
hello = nil  // force release. 

This means that I need to add capture lists to virtually closure in the program because I am almost always referencing self. I want to make sure that I have this right before making such a change. It seems that if that really were necessary, then they would have used a simpler example like the one I have.

Note that this is different than this question: Swift Closures - Capturing self as weak

This is also different than this question, even though the cause is the same, my question was about block ownership and that question was about deinit never being called ever, they are not exactly the same as it has been marked: Deinit method is never called - Swift playground

Community
  • 1
  • 1
possen
  • 8,596
  • 2
  • 39
  • 48
  • I just tested your code in the iPhone Simulator and I had the `deinit` called. But on Playground it seems that the block passed to `dispatch_async` is never called. – findall Apr 12 '15 at 03:42
  • 1
    Thanks, It does get called because if I remove the call to update deinit is called. I am starting to think it may just be a playground issue. Because when I ran it as a test application it did not require the [unowned self] and it did still call deinit. – possen Apr 12 '15 at 05:54
  • Yes, in playground the deinit is not necessarily called, like this answer explains: http://stackoverflow.com/a/24363716/2592349 – Dániel Nagy Apr 12 '15 at 06:48
  • Sure we can call it a duplicate since the same root cause. Definitely confusing and apparently no memory management conclusions you made from the Playground can be trusted. Although it is a bit strange that the playground deinited it in one case but not the other. Seems that if the playground were going to hold on to it in the capture list case and the non capture list state it would be consistent in what it holds on to. – possen Apr 12 '15 at 15:37
  • 1
    I disagree this question is an exact duplicate, the question was different, the root cause was the same as the mentioned question. So I don't think it should be downgraded. – possen May 03 '16 at 18:19

0 Answers0