Reputation: 21593
New to Swift and I'm wondering if I have to deal with (potentially) the same issue in this code as I did in Objective-C:
var itemB = EditableItem(title: "Item J")
itemB.onReturn = {(value) in
var s = itemB.title
println(value)
}
The closure has a reference to itemB
and itemB
has a reference to the closure. Does this lead to a cyclic reference and hence a memory leak in Swift or is Swift smart enough to make this a itemB
a weak var inside the closure?
If not, how can I fix this?
Upvotes: 1
Views: 42
Reputation: 2722
No, itemB inside the closure exist only as long as itemB is set outside.
Example, you can test this in a Playground.
Let pretend we have this Class mapping with your example:
Import Foundation
class EditableItem {
var title = ""
var onReturn: ((String)->Void)?
init(title: String) {
self.title = title
}
deinit {
println("Deinit")
}
}
And now we run code similar to yours:
// Using optional so that I can set it do nil = will dealloc
var itemB:EditableItem? = EditableItem(title: "Item J")
itemB!.onReturn = {(value) in
var s = itemB!.title
println(value)
}
// Execute to make sure anything would retain
itemB!.onReturn!("data")
// var is set to nil, same variable inside the closure
itemB = nil // Deinit will run
Same example with an variable retaining:
var retainer:EditableItem? = nil
var itemB:EditableItem? = EditableItem(title: "Item J")
itemB!.onReturn = {(value) in
retainer = itemB!
println(value)
}
// If onReturn() would not be executed, itemB would not be retained
itemB!.onReturn!("data")
// deinit will not be called
itemB = nil
And example to make the reference weak:
var retainer:EditableItem? = nil
var itemB:EditableItem? = EditableItem(title: "Item J")
// Make sure retainer is weak
itemB!.onReturn = { [weak retainer](value) in
retainer = itemB!
println(value)
// retainer is set here..
}
// retainer is nil here..
itemB!.onReturn!("data")
// retainer is nil here as well..
itemB = nil // And this will deinit
Upvotes: 1