Це майже так само, як прийнята відповідь, але з деяким додатковим діалогом (я мав з Роб Неп'єром, його іншими відповідями та Меттом, Олівером, Девідом з Слака) та посиланнями.
Дивіться коментарі в цій дискусії. Суть її полягає в:
+
сильно перевантажений (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
Щоб дізнатися, як записувати час складання, дивіться тут або тут
Інші подібні відповіді Роб Нап'єр на SO:
Чому додавання рядків займає стільки часу для створення?
Як об'єднати кілька масивів, не уповільнюючи компілятор?
Swift Array містить функцію, що збільшує час збирання
var statement = "create table if not exists \(self.tableName()) (\(columns))"
:?