关闭评估而无需评估

时间:2019-12-20 14:08:48

标签: swift closures

我正在编写一个记录函数,该函数也调用CocoaLumberjack函数(是的,我知道自定义记录器,因此选择不使用它)。我的职能是使用转发,但是我对“转发”的工作方式有疑问。 这是我的功能:

public func MyLogDebug(_ message: @autoclosure () -> String) {
    // some code
    MyLogMessage(message(), .debug)
}
public func MyLogMessage(_ message: @autoclosure () -> String, flag: DDLogFlag) {
    // some code
    if(myLogLevel.rawValue & flag.rawValue != 0) {
        DDLogDebug(message())
    }
}

我的问题是关于MyLogMessage(message(), .debug)函数调用。我知道避免字符串串联对提高日志性能确实有帮助,而且我可以看到,MyLogMessage内只有在通过日志级别的情况下才运行字符串关闭。但是,看起来MyLogDebug中的闭包也正在评估中。

我不想在MyLogDebug中运行闭包,因此我尝试将其更改为MyLogMessage(message, .debug),但是xcode给我一个错误:Add () to forward @autoclosure parameter

我上面的代码会评估MyLogDebug内部的闭包吗?如果是这样,还有另一种方法可以在不评估闭包参数的情况下转发闭包参数吗?

1 个答案:

答案 0 :(得分:1)

  

我上面的代码会评估MyLogDebug中的闭包吗?

不。呼叫message()将被@autoclosure中的MyLogMessage封装在一个闭包中,并且仅在随后在message()中调用MyLogMessage时才进行评估。


以下是一个独立的示例,可用于:

func DDLogDebug(_ message: String) {
    print("in DDLogDebug")
    print(message)
    print("leaving DDLogDebug")
}

public func MyLogDebug(_ message: @autoclosure () -> String) {
    // some code
    print("in MyLogDebug")
    MyLogMessage(message(), flag: true)
    print("leaving MyLogDebug")
}
public func MyLogMessage(_ message: @autoclosure () -> String, flag: Bool) {
    // some code
    print("in MyLogMessage")
    if (flag) {
        DDLogDebug(message())
    }
    print("leaving MyLogMessage")
}

MyLogDebug({ print("evaluated"); return "error message" }())

输出:

in MyLogDebug
in MyLogMessage
evaluated
in DDLogDebug
error message
leaving DDLogDebug
leaving MyLogMessage
leaving MyLogDebug

请注意,直到MyLogDebug中的DDLogDebug(message()),才会评估传递给MyLogMessage()的初始闭包。

如果在对flag的调用中将false更改为MyLogMessage(),则初始封闭将永远不会被评估。