Given:
typealias Action = () -> ()
var action: Action = { }
func doStuff(stuff: String, completion: @escaping Action) {
print(stuff)
action = completion
completion()
}
func doStuffAgain() {
print("again")
action()
}
doStuff(stuff: "do stuff") {
print("swift 3!")
}
doStuffAgain()
Is there any way to make the completion
parameter (and action
) of type Action?
and also keep @escaping
?
Changing the type gives the following error:
@escaping attribute only applies to function types
Removing the @escaping
attribute, the code compiles and runs, but doesn't seem to be correct since the completion
closure is escaping the scope of the function.
There is a SR-2552 reporting that @escaping
is not recognizing function type alias. that's why the error @escaping attribute only applies to function types
. you can workaround by expanding the function type in the function signature:
typealias Action = () -> ()
var action: Action? = { }
func doStuff(stuff: String, completion: (@escaping ()->())?) {
print(stuff)
action = completion
completion?()
}
func doStuffAgain() {
print("again")
action?()
}
doStuff(stuff: "do stuff") {
print("swift 3!")
}
doStuffAgain()
EDIT 1::
I was actually under a xcode 8 beta version where the bug SR-2552 was not resolved yet. fixing that bug, introduced a new one(the one you're facing) that is still open. see SR-2444.
The workaround @Michael Ilseman pointed as a temporary solution is remove the @escaping
attribute from optional function type, that keep the function as escaping.
func doStuff(stuff: String, completion: Action?) {...}
EDIT 2::
The SR-2444 has been closed stating explicitly that closures in parameters positions are not escaping and need them to be marked with @escaping
to make them escaping, but the optional parameters are implicitly escaping, since ((Int)->())?
is a synonyms of Optional<(Int)->()>
, optional closures are escaping.