Tuesday, October 11, 2016

Optional Non-Escaping Swift Closures

Ole Begemann:

However, it’s impossible to create a reference cycle with a non-escaping closure — the compiler can guarantee that the closure will have released all objects it captured by the time the function returns. For this reason, the compiler only requires explicit references to self for escaping closures. This makes non-escaping closures significantly more pleasant to use.


Beginning in Swift 3, non-escaping closures are now the default. If you want to allow a closure parameter to escape, you need to add the @escaping annotation to the type.


There’s a catch to the non-escaping-by-default rule: it only applies to closures in immediate function parameter position, i.e. any function argument that has a function type. All other closures are escaping.


There’s currently no way to force an optional closure to be non-escaping, but in many situations, you can probably avoid making the argument optional by providing a default value for the closure.

Or you can use overloading.

Update (2018-06-11): See also: Jesse Squires.

7 Comments RSS · Twitter

Even more rules to juggle in my head. :( Wasn't Swift suppose to make everything easier. Swift feels more and more like a trip to C++ bizarro land. Guess I'm getting too old... ;)

At one point I had abandoned C++ because I could do so much more, so much more quickly, in Perl. But Swift is starting to make C++ look simple by comparison.

Personally, I'm a bit worried when I see this kind of code:

func transform(_ n: Int, with f: ((Int) -> Int)?) -> Int {
    guard let f = f else { return n }
    return f(n)

works. It should be forbidden to use the same name for a parameter and a local var.

@someone: Welcome to the new Swift world, in which code is so concise, that there's no room for another variable name!

I initially was horrified too by this variable name shadowing business. It turns out it's actually a very nice way to make optional less of a pain to use. Same with casting and a number of other situations. Naming things is hard, remember?

I realize I also basically said optionals are annoying, but that's a different discussion.

@charles Yes, in cases like this I think shadowing is a feature. The optional is never referenced again, and then you don’t have to invent a new, more unwieldy, name for the “real” variable. So it makes the unwrapping feel like an operation on the parameter rather than adding a new binding.

[…] Previously: Optional Non-Escaping Swift Closures. […]

Leave a Comment