これは、受け入れられた回答とほとんど同じですが、追加の対話(ロブネイピアと彼の他の回答、およびSlackからのマット、オリバー、デビッド)とリンクが追加されています。
このディスカッションのコメントを参照してください。その要点は次のとおりです。
+
非常に過負荷になっている(Appleが一部のケースでこれを修正したようです)
+
オペレータは、あなたが4つの文字列を連結しているので、もしそれが27の異なる機能を持っている今のところ大きく、過負荷になっているあなたは3つの持っている。すなわち+
、コンパイラはしている事業者チェックそれでは27 ^ 3倍という、27事業者の間で、それぞれの時間を。しかし、それだけではありません。
あり、チェックかどうかを確認するためにlhs
とrhs
の+
、彼らはそれがコアに通じ呼び出しをされている場合の機能は両方とも有効であるappend
と呼ばれるが。そこでは、いくらか集中的なチェックが行われる可能性があることがわかります。文字列が不連続に格納されている場合、これは、処理している文字列が実際にNSStringにブリッジされている場合に発生する可能性があります。その後、Swiftはすべてのバイト配列バッファーを単一の連続したバッファーに再アセンブルする必要があり、途中で新しいバッファーを作成する必要があります。そして、最終的に、連結しようとしている文字列を含む1つのバッファーを取得します。
一言で言えば、あなたを遅くするコンパイラチェックの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
whichがにハードコードされているを使用することによりString
、コンパイラーはすべての適合タイプをループする必要がなくなります。ExpressibleByStringLiteral
コンパイル時間を記録する方法については、ここまたはここを参照してください
SOでのロブネイピアの他の同様の回答:
なぜ文字列の追加に時間がかかるのですか?
コンパイラを遅くせずに複数の配列をマージするにはどうすればよいですか?
Swift配列に関数が含まれているとビルド時間が長くなります
var statement = "create table if not exists \(self.tableName()) (\(columns))"
かどうか確認しましたか?