我有这个自定义运算符:
infix operator ?> : NilCoalescingPrecedence
func ?> (lhs: Any?, rhs: @autoclosure ()->Any) {
if lhs == nil {
print("lhs is nil")
rhs()
}
}
用法:
optional ?> {
print("executing")
}
问题是,当lhs
为零时,闭包不会执行。在控制台中,"lhs is nil"正在打印,但之后没有"执行"正在打印。如何执行"lhs is nil"打印语句但不执行rhs
?
导致这种行为的是@autoclosure
,如果您删除它,它可以正常工作。
这是因为@autoclosure
会将您的闭包包装成闭包,所以现在您有这样的东西:
{ { print("executing") } }
外闭合返回Any
,对吧?因此,它只会返回闭包{ print("executing") }
而不执行任何其他操作。
如果要保留@autoclosure
,可以这样使用运算符:
optional ?> print("executing")
解决方案似乎是使用完全相同的签名向运算符添加重载,除了它没有@autoclosure
注释,并且两者的rhs
都必须返回Void
而不是Any
。
infix operator ?> : NilCoalescingPrecedence
func ?> (lhs: Any?, rhs: @autoclosure ()->Void) {
if lhs == nil {
print("lhs is nil")
rhs()
}
}
func ?> (lhs: Any?, rhs: ()->Void) {
if lhs == nil {
print("lhs is nil")
rhs()
}
}
这样,如果我这样做:
optional ?> doSomething()
@autoclosure
将被调用,无论doSomething()
是否返回任何内容。
如果我这样做:
optional ?> {
doSomething()
doSomethingElse()
}
没有@autoclosure
的那个将被调用,因为闭包的类型是()->Void
.
您需要在闭包方法的末尾添加()
,如下所示
optional ?> {
print("executing")
}()
如果您打算在运算符后添加大括号,则可以将其实现(无需将rhs
声明为自动闭包(:
infix operator ?> : NilCoalescingPrecedence
func ?> (lhs: Any?, rhs: ()->Any) {
if lhs == nil {
print("lhs is nil")
rhs()
}
}
var myString: String? = ""
// some case that made "string" to be nil...
myString = nil
myString ?> {
print("executing")
}
但是,声明自动闭包的目的是包装作为参数传递给函数的表达式:
这种语法便利性允许您省略函数 参数,通过编写普通表达式而不是显式表达式 关闭。
官方 Swift 文档 - 关闭、自动关闭
这意味着不需要大括号,这在与操作员一起工作时应该更自然:
infix operator ?> : NilCoalescingPrecedence
func ?> (lhs: Any?, rhs: @autoclosure ()->Any) {
if lhs == nil {
print("lhs is nil")
rhs()
}
}
var myString: String? = ""
// some case that made "string" to be nil...
myString = nil
// you could use your operator like:
myString ?> print("executing")
但是等等!
可能会面临一个问题是:如果在运算符之后添加一段代码怎么办?
好吧,毫无疑问,您必须添加大括号:
let doSomething = {
print("executing")
print("second line of execution")
print("third line of execution")
}
myString ?> doSomething()