如何在迅速中做出一个可选的关闭?

我试图在 Swift 中声明一个可选闭包的参数。我声明的函数如下:

class Promise {


func then(onFulfilled: ()->(), onReject: ()->()?){
if let callableRjector = onReject {
// do stuff!
}
}


}

但 Swift 抱怨“条件中的绑定值必须是可选类型”,其中声明了“ if let”。

37697 次浏览

You should enclose the optional closure in parentheses. This will properly scope the ? operator.

func then(onFulfilled: ()->(), onReject: (()->())?){
if let callableRjector = onReject {
// do stuff!
}
}

To make the code even shorter we can use nil as default value for onReject parameter and optional chaining ?() when calling it:

func then(onFulfilled: ()->(), onReject: (()->())? = nil) {
onReject?()
}

This way we can omit onReject parameter when we call then function.

then({ /* on fulfilled */ })

We can also use trailing closure syntax to pass onReject parameter into then function:

then({ /* on fulfilled */ }) {
// ... on reject
}

Here is a blog post about it.

Since I assume, that this "optional" closure should simply do nothing, you could use a parameter with an empty closure as default value:

func then(onFulfilled: ()->(), onReject: ()->() = {}){
// now you can call your closures
onFulfilled()
onReject()
}

this function can now be called with or without the onReject callback

then({ ... })
then({ ... }, onReject: { ... })

No need for Swift's awesome Optionals? here!

Maybe it's a cleaner way. Specially when the closure has complicated parameters.

typealias SimpleCallBack = () -> ()


class Promise {


func then(onFulfilled: SimpleCallBack, onReject: SimpleCallBack?){
if let callableRjector = onReject {
// do stuff!
}
}


}

As an alternative to creating a TypeAlias or using well-placed parentheses, there's always Swift's Optional type itself. It can be used just like your typical Java (or in this case Swift) Generic Array syntax Optional<() -> ()> OR in context:

func callAClosure(firstClosure: () -> (), secondClosure: Optional<() -> ()> {
if let secondClosure = secondClosure {
secondClosure()
}
else { firstClosure() }
}

I find this to be fairly clean. As a bonus, in the context of SwiftUI where generics can be common, like struct CommonList<T: View>: View then you don't have to create a typealias that only gets used once (commonly the init function for that struct). Instead, you make one simple optional closure parameter, and you're all done!

Hopefully this helps anyone that runs into the issue and happy coding!