@escaping closure as an argument of another closure

Hi all, I'm facing a problem that I came up with the following code (simplified for illustration purposes):

typealias Handler = (String) -> Void

// class B scope
var handlerSaver: Handler?

// saves the closure parameter (handler) to be executed later
classA.foo: ((Handler) -> Void) = { handler in
    // error: Assigning non-escaping parameter 'handler' to an @escaping closure
    handlerSaver = handler
}
// got stuff ...
handlerSaver("stuff")

// class A scope
var foo: ((Handler) -> Void)?

var handler = { (string: String) -> Void in
    print("handle this \(string)")
}
// execute foo's closure with another closure (handler) as argument
foo?(handler)

Can this error be fixed? In other words I would like that class A calls foo but its handler being called later by class B. Is there any other way to achieve this instead of implementing a func handler(_ string: String) in class A; so the class B would call for it like so classA.handler("stuff") ?

Thanks!

If I got you correctly then this should help:

// got stuff ...
handlerSaver?("stuff")
            ^ missing

// class A scope
var foo: ((@escaping Handler) -> Void)?
           ^~~~~~~~~ this is missing

Just reshuffled everything a little:

typealias Handler = (String) -> Void

class A {
  var foo: ((@escaping Handler) -> Void)?
}

let classA = A()

// class B scope
var handlerSaver: Handler?

// saves the closure parameter (handler) to be executed later
classA.foo = { handler in
  // error: Assigning non-escaping parameter 'handler' to an @escaping closure
  handlerSaver = handler
}

var handler = { (string: String) -> Void in
  print("handle this \(string)")
}
// execute foo's closure with another closure (handler) as argument
classA.foo?(handler)

// got stuff ...
handlerSaver?("stuff")

Prints "handle this stuff".

2 Likes

Many thanks for the detailed answer!

The ((@escaping Handler) -> Void)? did the trick. I thought that the @escaping keyword could only be used in func declarations.