我对Swift还是比较新的。我多次看到过的一件事是,在Swift 3中,@ noescape属性已成为默认属性并被弃用。但我不认为这是完全正确的。
我已经编写了自己的日志库。截至昨天,这是30种(实际上是36种)公共记录方法中的一种:
public static func verbose(_ logItem1 : @autoclosure @escaping () -> Any?,
_ logItem2 : @autoclosure @escaping () -> Any?,
funcFile : StaticString = #file,
funcName : StaticString = #function,
lineNumber : Int = #line) {
if .eVerbose >= _thresholdValue {
doLogging(logLevel: .eVerbose,
funcFile: funcFile, funcName: funcName, lineNumber: lineNumber,
logItem1, logItem2)
}
}
这里是被调用的私有方法的签名:
private static func doLogging(logLevel : ELogLevel, funcFile : StaticString,
funcName : StaticString, lineNumber : Int,
_ logItemClosures : () -> Any?...) {
...
let logItemsFormatted = formatLogArguments(logItemClosures)
...
}
private static func formatLogArguments(_ logItemClosures : [() -> Any?])
-> (messageText : String?, errorText : String?) {
...
}
闭包都是用formatLogArguments()方法计算的。
我使用" @autoclosure @escaping"在"日志项目"参数的灵感来自于在GitHub上查看几个开源日志库。 (XCGLogger看起来很棒。)
但今天我正在阅读更多关于闭包的内容,我开始思考 - 这些闭包不是真的"转义",它们都会在外部日志方法返回之前得到评估(或不评估)。所以我尝试从所有日志方法中删除@escaping属性。 Swift编译器给我带来了30条错误消息。
然后,只是为了它,我改变了两个私有方法的签名,如下所示:
private static func doLogging(logLevel : ELogLevel, funcFile : StaticString,
funcName : StaticString, lineNumber : Int,
_ logItemClosures : @noescape () -> Any?...) {
...
}
private static func formatLogArguments(_ logItemClosures : [@noescape () -> Any?])
-> (messageText : String?, errorText : String?) {
...
}
现在Swift编译器很开心,我的测试程序运行正常。
所以也许@noescape仍然存在且有用吗?
(我还没有尝试分析编译器的输出,看看它是否已经过优化 - 我的Swift技能还没有达到目的。)