Problem with non-escaping closures in Swift 3
I have extension Array
in the form:
extension Array
{
private func someFunction(someClosure: (() -> Int)?)
{
// Do Something
}
func someOtherFunction(someOtherClosure: () -> Int)
{
someFunction(someClosure: someOtherClosure)
}
}
But I get the error message: Passing non-escaping parameter 'someOtherClosure' to function expecting an @escaping closure
.
Both closures are indeed not escaped (by default), and the explicit addition @noescape
to someFunction
gives a warning indicating that this is the default in Swift 3.1.
Any idea why I am getting this error?
source to share
As already mentioned, closures Optional
escaping
. Besides:
Swift 3.1 has a helper function withoutActuallyEscaping that might be helpful here. It marks the closure escaping
only for its use within the traversed closure, so you don't have to expose the attribute to escaping
the function signature.
Can be used like this:
extension Array {
private func someFunction(someClosure: (() -> Int)?) {
someClosure?()
}
func someOtherFunction(someOtherClosure: () -> Int) {
withoutActuallyEscaping(someOtherClosure) {
someFunction(someClosure: $0)
}
}
}
let x = [1, 2, 3]
x.someOtherFunction(someOtherClosure: { return 1 })
Hope this is helpful!
source to share
The problem is that the options (in this case (()-> Int)?
) are Enums that capture their value. If this value is a function, it should be used with @escaping
, because it is indeed captured by the optional. In your case, it gets tricky because the closure captured by the optional automatically captures the other closure. Therefore, it someOtherClosure
should be marked as @escaping
.
You can check the following code in the playground to confirm this:
extension Array
{
private func someFunction(someClosure: () -> Int)
{
// Do Something
}
func someOtherFunction(someOtherClosure: () -> Int)
{
someFunction(someClosure: someOtherClosure)
}
}
let f: ()->Int = { return 42 }
[].someOtherFunction(someOtherClosure: f)
source to share