LongNV
LongNV

Reputation: 902

Object is not deallocated when capturing by closures in Swift

The Swift Programming Language guide has the following example:

class HTMLElement {

    let name: String
    let text: String?

    @lazy var asHTML: () -> String = {
        [unowned self] in
        if let text = self.text {
            return "<\(self.name)>\(text)</\(self.name)>"
        } else {
            return "<\(self.name) />"
        }
    }

    init(name: String, text: String? = nil) {
        self.name = name
        self.text = text
    }

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

}
var paragraph:HTMLElement? = HTMLElement(name: "p", text: "hello, world")
println("\(paragraph!.asHTML())")
paragraph = nil

It was expected to print out the string in deinit() method, but it hadn't printed anything. It mean to me that the object is still alive, and has strong reference cycle with the closure. Does anyone get the same issue?

Upvotes: 3

Views: 2339

Answers (1)

Joshua Weinberg
Joshua Weinberg

Reputation: 28688

Do this with weak capture instead of unowned

class HTMLElement {

    let name: String
    let text: String?

    @lazy var asHTML: () -> String = {
        [weak self] in
        if let text = self?.text {
            return "<\(self?.name)>\(text)</\(self?.name)>"
        } else {
            return "<\(self?.name) />"
        }
    }

    init(name: String, text: String? = nil) {
        self.name = name
        self.text = text
    }

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

}
var paragraph:HTMLElement? = HTMLElement(name: "p", text: "hello, world")
println("\(paragraph!.asHTML())")
paragraph = nil

Upvotes: 2

Related Questions