我已将Swift编译器标志-warn-long-function-bodies
设置为90毫秒,以查看我的项目中哪些函数编译时间过长(由于类型检查)。
我有以下方法:
func someKey(_ sectionType: SectionType, row: Int) -> String {
let suffix = row == 0 ? "top" : "content"
return "\(sectionType)_\(suffix)"
}
(SectionType
是一个支持字符串的枚举)
如上所述,2017款MacBook Pro需要 96ms 。我尝试的第一件事是绕过字符串插值并使用\(sectionType.rawValue)
而不是\(sectionType)
,但现在它给了我 106 ms 。错误的举动......
接下来,我改变了:
let suffix = row == 0 ? "top" : "content"
为:
let suffix = "top"
警告消失了,因此三元运算符导致了问题。
我尝试了这个:
let suffix: String = { // Note the type annotation!
if row == 0 {
return "top"
}
return "content"
}()
...但现在是闭包需要97毫秒(整个功能,101)。
我甚至尝试过更明确的:
let suffix: String = {
if row == 0 {
return String("top")
} else {
return String("content")
}
}()
......我闭嘴:94ms;功能:98ms。
发生了什么事?
我的90毫秒限制是否太低?我知道(是吗?)字典文字的类型检查错误,但这看起来完全不同......?
我的环境是Xcode 8.3.2(8E2002),
斯威夫特:Apple Swift version 3.1 (swiftlang-802.0.53 clang-802.0.42)
但等等!还有更多......
我试过这个函数体:
func someKey(_ sectionType: SectionType, row: Int) -> String {
if row == 0 {
return "\(sectionType.rawValue)_top"
} else {
return "\(sectionType.rawValue)_content"
}
}
......需要97ms~112ms!?
附录:我将该函数和枚举移植到一个干净的,最小的项目(单视图应用程序)设置相同的警告,但它不会发生。我确信整个项目正在以某种方式影响这一方法,但还不能确定如何...
附录2 :我测试了我的函数的静态版本:使用固定后缀“top”而不管row
的值(这需要不到90毫秒并且不会触发警告) ,但添加了以下if
块:
func someKey(_ sectionType: SectionType, row: Int) -> String {
if row == 0 {
print("zero")
} else {
print("non-zero")
}
let suffix: String = "top"
return "\(sectionType)_\(suffix)"
}
这让我回到了96~98毫秒! 因此,在将行与零进行比较时会出现问题吗?
解决方法:我一直在玩我的代码并以某种方式发现如果我用if
语句替换switch
块,问题就会消失:
func someKey(_ sectionType: SectionType, row: Int) -> String {
let suffix: String = {
switch row {
case 0:
return "top"
default:
return "content"
}
}()
return "\(sectionType)_\(suffix)"
}
(我不会回答我自己的问题,因为我不认为这是对实际情况的解释)
答案 0 :(得分:1)
我认为这是三元运算符。
我在Xcode 11(〜93ms)中得到了类似的结果,但是使用以下命令,编译时间减少到〜23ms:
func someKey(_ sectionType: SectionType, row: Int) -> String {
var suffix = "top"
if row != 0 {
suffix = "content"
}
return "\(sectionType)_\(suffix)"
}
通过更改这条线上的逻辑,我认为我们可以证明它是三元逻辑,因为该方法可减少到〜1ms。我刚刚将row设为布尔值。
func someKey(_ sectionType: SectionType, row: Bool) -> String {
let suffix = row ? "top" : "content"
return "\(sectionType)_\(suffix)"
}
同样(无双关语)将三元逻辑更改为let suffix = row != 0 ? "top" : "content"
可使编译时间减半。这与我的第一个代码块相当。与|=
相比,==
对Swift的理解更快。