If I have some code that takes a closure, and self
is implicitly captured, can I make it cause a compiler warning? Is there some flag I can add to the compiler command for this?

- 374
- 3
- 11
-
On my best knowladge you don't ... – user3441734 Jan 06 '16 at 20:27
-
Objective C compiler warns: https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/ProgrammingWithObjectiveC/WorkingwithBlocks/WorkingwithBlocks.html "The compiler will warn you for a simple example like this, but a more complex example might involve multiple strong references between objects to create the cycle, making it more difficult to diagnose." – Display Name Feb 23 '18 at 10:09
2 Answers
Not exactly. But there is something that addresses what's presumably the reason you'd want this warning — to prevent situation where a closure capturing self
can cause a retain cycle...
The potential retain cycle from capturing self
in a closure comes up when the closure is passed as a parameter to a function but is used after the function returns — that is, the lifetime of the closure (and anything captured in it) "escapes" the context in which it's written. When the closure escapes, it has to be sure it still has access to the things it uses (like self
and any properties or methods thereof), so we get into memory management and possible retain cycles, [weak self]
/strongSelf
, etc.
With @noescape
, you can declare that closures passed as parameters to a function will not escape the calling context, and as such don't require the extra memory management overhead for closures that do. And the compiler can apply some other optimizations that make running your function and its closure faster.
func someFunctionWithNoescapeClosure(@noescape closure: () -> Void) {
closure()
}
Within a @noescape
closure, you can then access methods/properties on self
without explicitly writing self.
, because you're not capturing self
anymore. And, once you label a parameter @noescape
, if you try to do anything that would permit it to escape (say, take the closure from the parameter and assign it to a stored property), you'd get a compiler error (not just a warning).
For the full writeup from Apple, see Nonescaping Closures in The Swift Programming Language. And this post provides an alternate perspective that might explain things further.

- 124,678
- 26
- 272
- 326
-
1Hi rickster, thanks for your comment. Unfortunately, my case is that there are many people in my project who forget to make self weak, when calling framework APIs that take closures, specifically, RxSwift and RxCocoa. Your solution can work in some cases, but when we are calling framework code, how should this be handled? – user3352495 Jan 06 '16 at 22:26
-
If you're working with a framework that permits escaping closures but doesn't need to, you could write adapter APIs that redeclare/pass-through those parameters as `@noescape`, and require your team to use the adapters instead of the original APIs. (Something you could enforce easily in pre-commit hooks or whatever.) Otherwise... – rickster Jan 06 '16 at 22:45
-
1... you're beyond what the compiler can do and into the realm of static analysis (not least because whether any particular escaping closure *can* leak `self` doesn't guarantee whether it will). Xcode does have a static analyzer for catching problems *like* this, but I don't believe it currently catches this specific kind of issue. [That'd make a good feature request!](http://bugreport.apple.com) – rickster Jan 06 '16 at 22:45