How does one make an optional closure in swift?
You should enclose the optional closure in parentheses. This will properly scope the ?
operator.
func then(onFulfilled: ()->(), onReject: (()->())?){
if let callableRjector = onReject {
// do stuff!
}
}
Optional closures in Swift 4
Distinguish between single-tuple and multiple-argument function types
// Declare closure
var checksPerformed: (() -> ())? // Declaration
// Call when needed
checksPerformed?()
//Only executes when checksPerformed is called
checksPerformed = {
// do stuff here
}
Optional closures in swift 5
I'm assuming when you say "how to write an optional closure" you mean "how to call an optional closure", because you've written the closure parameter just fine, but you're just not calling it correctly.
To call an optional closure, you need to unwrap it first. Either:
completion?()
or:
if let unwrappedCompletion = completion {
unwrappedCompletion()
}
Passing optional closure to the View
Change your variable let to var.
var action: (() -> Void)? = nil
Swift optional escaping closure parameter
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.
Swift optional escaping closure
Clarification:
For understanding the case, implementing the following code would be useful:
typealias completion = () -> ()
enum CompletionHandler {
case success
case failure
static var handler: completion {
get { return { } }
set { }
}
}
func doSomething(handlerParameter: completion) {
let chObject = CompletionHandler.handler = handlerParameter
}
At the first look, this code seems to be legal, but it's not! you would get compile-time error complaining:
error: assigning non-escaping
parameter 'handlerParameter' to an @escaping closurelet chObject = CompletionHandler.handler = handlerParameter
with a note that:
note: parameter 'handlerParameter' is implicitly non-escaping func
doSomething(handlerParameter: completion) {
Why is that? the assumption is that the code snippet has nothing to do with the @escaping
...
Actually, since Swift 3 has been released, the closure will be "escaped" if it's declared in enum, struct or class by default.
As a reference, there are bugs reported related to this issue:
- Optional closure type is always considered @escaping.
- @escaping failing on optional blocks.
Although they might not 100% related to this case, the assignee comments are clearly describe the case:
First comment:
The actual issue here is that optional closures are implicitly
@escaping right now.
Second comment:
That is unfortunately the case for Swift 3. Here are the semantics for
escaping in Swift 3:1) Closures in function parameter position are
non-escaping by default2) All other closures are escaping
Thus, all generic type argument closures, such as Array and Optional, are escaping.
Obviously, Optional
is enum.
Also -as mentioned above-, the same behavior would be applicable for the classes and structs:
Class Case:
typealias completion = () -> ()
class CompletionHandler {
var handler: () -> ()
init(handler: () -> ()) {
self.handler = handler
}
}
func doSomething(handlerParameter: completion) {
let chObject = CompletionHandler(handler: handlerParameter)
}
Struct Case:
typealias completion = () -> ()
struct CompletionHandler {
var handler: completion
}
func doSomething(handlerParameter: completion) {
let chObject = CompletionHandler(handler: handlerParameter)
}
The two above code snippets would leads to the same output (compile-time error).
For fixing the case, you would need to let the function signature to be:
func doSomething( handlerParameter: @escaping completion)
Back to the Main Question:
Since you are expecting that you have to let the completion:(()->())?
to be escaped, that would automatically done -as described above-.
optional closure property in Swift
I believe you just need to wrap the closure type in parenthesis, like so:
var respondToButton:((sender: UIButton) -> Bool)?
Alternatively if this is a closure type you're going to use often you can create a typealias
to make it more readable:
typealias buttonResponder = (sender: UIButton) -> Bool
then in your class:
var respondToButton:buttonResponder?
Related Topics
How to Create Usdz File Using Xcode Converter
Cfrunloop in Swift Command Line Program
How to Convert Unix Epoch Time to Date and Time in iOS Swift
What Is the "Some" Keyword in Swift(Ui)
Xcode 8 Beta 3 Use Legacy Swift Issue
Swift Constants: Struct or Enum
Append Text or Data to Text File in Swift
How to Generate a Random Number in Swift Without Repeating the Previous Random Number
How to Get the Count of a Swift Enum
Dyld: Library Not Loaded: @Rpath/Libswift_Stdlib_Core.Dylib
Why Can't I Pass a Protocol.Type to a Generic T.Type Parameter
Attach Parameter to Button.Addtarget Action in Swift
What Is a Good Example to Differentiate Between Fileprivate and Private in Swift3