Reputation: 891
Is there any way to indicate to a "client" of a specific method that a closure parameter is going to be retained?
For instance, having the following code:
import Foundation
typealias MyClosureType = () -> Void
final class MyClass {
private var myClosure: MyClosureType?
func whatever(closure: MyClosureType?) {
myClosure = closure
}
}
Anyone could start using this class and passing closures to the method whatever
without any idea about if it is actually being retained or not. Which is error prone and could lead to memory leaks.
For instance, a "client" doing something like this, would be never deallocated
final class MyDummyClient {
let myInstance = MyClass()
func setUp() {
myInstance.whatever {
self.whateverHandler()
}
}
func whateverHandler() {
print("Hey Jude, don't make it bad")
}
}
That is why I would like to know if there is any way to prevent this type of errors. Some type of paramater that I could add to the definition of my method whatever
which gives a hint to the client about the need to weakify to avoid leaks
Upvotes: 3
Views: 223
Reputation: 7746
With the specific case you're presenting the closure itself is the only thing that will be retained, so if you correctly add [weak self] to your closure when you call it there shouldn't be any issues.
I'm not sure what issue you're trying to protect against, but you might also thing about using delegation (protocols) rather than a closure.
Upvotes: 0
Reputation: 118691
Whether the closure parameter is escaping or non-escaping is some indication to the caller whether it might be retained. In particular, a non-escaping closure param cannot be retained by a function call.
Per SE-0103, non-escaping closures (currently marked @noescape
) will become the default in Swift 3, and you'll have to write @escaping
if you want to save the closure, so situations like this will become a little more obvious.
Otherwise, there is no language feature to help you here. You'll have to solve this problem with API design and documentation. If it's something like a handler, I'd recommend a property, obj.handler = { ... }
, or a method like obj.setHandler({ ... })
or obj.addHandler({ ... })
. That way, when reading the code, you can easily tell that the closure is being saved because of the =
or set
or add
.
(In fact, when compiling Obj-C, Clang explicitly looks for methods named set...:
or add...:
when determining whether to warn the user about retain cycles. It's possible a similar diagnostic could be added to the Swift compiler in the future.)
Upvotes: 2