Это почти то же самое, что принятый ответ, но с некоторым дополнительным диалогом (я имел с Робом Нейпиром, его другими ответами и Мэттом, Оливером, Дэвидом из Slack) и ссылками.
Смотрите комментарии в этой дискуссии. Суть этого:
+ сильно перегружен (в некоторых случаях 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))"?