Jest to prawie taka sama jak zaakceptowana odpowiedź, ale z dodatkowymi dialogami (miałem z Robem Napierem, jego innymi odpowiedziami oraz Mattem, Oliverem, Davidem ze Slacka) i linkami.
Zobacz komentarze w tej dyskusji. Istota tego jest taka:
+ jest mocno przeciążony (wydaje się, że Apple naprawił to w niektórych przypadkach)
+Operator jest mocno przeciążony, ponieważ od teraz ma 27 różnych funkcji, więc jeśli złączenie 4 strings czyli masz 3 +operatorów kompilator musi się sprawdzić między 27 operatorów za każdym razem, więc to 27 ^ 3 razy. Ale to nie wszystko.
Istnieje również sprawdzić , czy lhsi rhsz +funkcjami są zarówno ważne, jeżeli są one wywołuje aż do jądrze appendnazywa. Jak widać , może dojść do szeregu dość intensywnych kontroli . Jeśli ciąg jest przechowywany w sposób nieciągły, co wydaje się mieć miejsce, jeśli ciąg, z którym masz do czynienia, jest faktycznie mostkowany do NSString. Swift musi następnie ponownie złożyć wszystkie bufory tablicy bajtów w jeden ciągły bufor, co wymaga tworzenia nowych buforów po drodze. a potem w końcu otrzymujesz jeden bufor, który zawiera ciąg, który próbujesz połączyć.
Krótko mówiąc, istnieją 3 klastry kontroli kompilatora, które spowalniają Cię, tj. Każde wyrażenie podrzędne musi zostać ponownie przemyślane w świetle wszystkiego, co może zwrócić . W rezultacie łączenie ciągów za pomocą interpolacji, tj. Używanie " My fullName is \(firstName) \(LastName)"jest znacznie lepsze niż "My firstName is" + firstName + LastNameponieważ interpolacja nie ma żadnego przeciążenia
Swift 3 wprowadził pewne ulepszenia. Aby uzyskać więcej informacji, przeczytaj artykuł Jak scalić wiele tablic bez spowalniania kompilatora? . Niemniej jednak +operator jest nadal przeciążony i lepiej jest używać interpolacji ciągów dla dłuższych ciągów
Wykorzystanie opcji (bieżący problem - dostępne rozwiązanie)
W tym bardzo prostym projekcie:
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"
}
Czas kompilacji funkcji jest następujący:
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()
Zwróć uwagę, jak szalony jest czas trwania kompilacji concatenatedOptionals.
Można to rozwiązać, wykonując:
let emptyString: String = ""
func concatenatedOptionals() -> String {
return (p2.firstName ?? emptyString) + emptyString + (p2.lastName ?? emptyString) + (p2.status ?? emptyString)
}
który się kompiluje 88ms
Główną przyczyną problemu jest to, że kompilator nie identyfikuje ""pliku jako String. Właściwie toExpressibleByStringLiteral
Kompilator zobaczy ??i będzie musiał przeglądać wszystkie typy, które są zgodne z tym protokołem , aż znajdzie typ, który może być domyślny String. Używając emptyStringktóre jest zakodowane na stałe String, kompilator nie musi już przechodzić przez wszystkie zgodne typyExpressibleByStringLiteral
Aby dowiedzieć się, jak rejestrować czasy kompilacji, zobacz tutaj lub tutaj
Inne podobne odpowiedzi Roba Napiera na SO:
Dlaczego tworzenie dodawania ciągów trwa tak długo?
Jak połączyć wiele tablic bez spowalniania kompilatora?
Swift Array zawiera funkcję, która wydłuża czas kompilacji
var statement = "create table if not exists \(self.tableName()) (\(columns))":?