Skip to content

Instantly share code, notes, and snippets.

@nicnocquee
Created March 17, 2017 14:17
Show Gist options
  • Select an option

  • Save nicnocquee/05899cf47e6bdc062d96dc51f3fc84c1 to your computer and use it in GitHub Desktop.

Select an option

Save nicnocquee/05899cf47e6bdc062d96dc51f3fc84c1 to your computer and use it in GitHub Desktop.
Why is this not creating strong reference cycles?
class HTMLElement {
let name: String
let text: String?
lazy var asHTML: () -> String = {
[unowned self] in // without this capture list, self is captured strongly in the closure
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 {
print("\(name) is being deinitialized")
}
}
var h2: HTMLElement? = HTMLElement(name: "h2", text: "Hello")
// why don't the following create strong reference cycles?
h2!.asHTML = {
return "Huh \(h2!.name)" // h2 is not captured strongly here? why?
}
print(h2!.asHTML())
h2 = nil // h2 still calls deinit
@nicnocquee
Copy link
Author

So it seems like it's not strong reference cycle because h2 is optional.

OTOH, the following causes strong reference cycle

func something () {
    let h2: HTMLElement = HTMLElement(name: "h2", text: "Hello")
    h2.asHTML = {
        [unowned h2] in // without this capture list, it creates strong reference cycle
        return "Huh \(h2.name)"
    }
    print(h2.asHTML())
}

something()

Without [unowned h2] in, h2 instance is never deallocated because the closure captures it strongly.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment