这几乎与接受的答案相同,但是增加了一些对话(我与Rob Napier,他的其他答案以及Slack的Matt,Oliver和David进行了对话)和链接。
请参阅此讨论中的评论。其要点是:
+
严重超载(Apple似乎在某些情况下已解决此问题)
该+
运营商的负荷过重,截至目前有27个不同的功能,所以如果你是串联4串,即你有3个+
运营商的编译器来检查,每次27个运营商之间,所以这是27 ^ 3倍。但这不是。
还有一个检查,看看是否lhs
和rhs
的+
功能是,如果他们是它调用通过核心的两个有效的append
调用。在这里,您可以看到许多可能会进行的密集检查。如果字符串是非连续存储的,则实际上是将要处理的字符串桥接到NSString时。然后,Swift必须将所有字节数组缓冲区重新组装为一个连续的缓冲区,这需要沿途创建新的缓冲区。然后最终得到一个缓冲区,其中包含要连接在一起的字符串。
简而言之,有3个编译器检查集群会减慢您的速度,即,必须根据可能返回的所有内容重新考虑每个子表达式。结果,使用插值连接字符串(即使用" My fullName is \(firstName) \(LastName)"
)要比"My firstName is" + firstName + LastName
插值没有任何重载要好得多
Swift 3 进行了一些改进。有关更多信息,请阅读如何合并多个数组而不降低编译器速度?。尽管如此,+
操作员仍然过载,最好对较长的字符串使用字符串插值
可选选项的使用(正在进行的问题-解决方案可用)
在这个非常简单的项目中:
import UIKit
class ViewController: UIViewController {
let p = Person()
let p2 = Person2()
func concatenatedOptionals() -> String {
return (p2.firstName ?? "") + "" + (p2.lastName ?? "") + (p2.status ?? "")
}
func interpolationOptionals() -> String {
return "\(p2.firstName ?? "") \(p2.lastName ?? "")\(p2.status ?? "")"
}
func concatenatedNonOptionals() -> String {
return (p.firstName) + "" + (p.lastName) + (p.status)
}
func interpolatedNonOptionals() -> String {
return "\(p.firstName) \(p.lastName)\(p.status)"
}
}
struct Person {
var firstName = "Swift"
var lastName = "Honey"
var status = "Married"
}
struct Person2 {
var firstName: String? = "Swift"
var lastName: String? = "Honey"
var status: String? = "Married"
}
这些函数的编译时间如下:
21664.28ms /Users/Honey/Documents/Learning/Foundational/CompileTime/CompileTime/ViewController.swift:16:10 instance method concatenatedOptionals()
2.31ms /Users/Honey/Documents/Learning/Foundational/CompileTime/CompileTime/ViewController.swift:20:10 instance method interpolationOptionals()
0.96ms /Users/Honey/Documents/Learning/Foundational/CompileTime/CompileTime/ViewController.swift:24:10 instance method concatenatedNonOptionals()
0.82ms /Users/Honey/Documents/Learning/Foundational/CompileTime/CompileTime/ViewController.swift:28:10 instance method interpolatedNonOptionals()
注意编译持续时间concatenatedOptionals
是多么疯狂。
这可以通过以下方法解决:
let emptyString: String = ""
func concatenatedOptionals() -> String {
return (p2.firstName ?? emptyString) + emptyString + (p2.lastName ?? emptyString) + (p2.status ?? emptyString)
}
编译在 88ms
问题的根本原因是编译器无法将识别""
为String
。其实是ExpressibleByStringLiteral
编译器将看到??
并且将不得不遍历所有符合此协议的类型,直到找到可以默认为的类型为止String
。通过使用emptyString
硬编码为String
,编译器不再需要遍历所有符合类型的ExpressibleByStringLiteral
要了解如何记录编译时间,请参见此处或此处
Rob Napier关于SO的其他类似答案:
为什么字符串加法需要这么长时间才能构建?
如何合并多个数组而不降低编译器的速度?
Swift Array包含使构建时间变长的功能
var statement = "create table if not exists \(self.tableName()) (\(columns))"
?