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?

- UPDATE - Attached screenshot: enter image description here

+3


source to share


3 answers


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!

+4


source


Additional locks are always escaped.

Why? This is because the optional (which is an enumeration) completes the closure and internally stores it.



There is a great article on quirks @escaping

here .

+5


source


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)   

      

0


source







All Articles