Я исхожу из фона С#, где System.String неизменен, а конкатенация строк относительно дорога (поскольку для этого требуется перераспределить строку), мы знаем, что вместо этого используется тип StringBuilder, поскольку он предопределяет больший буфер, где одиночные символы (Char, 16-битный тип значения), а короткие строки могут быть объединены дешево без дополнительного распределения.
Я переношу некоторый код С# в Swift, который читает из битового массива ([Bool]) в индексах под октета с длиной символов менее 8 бит (это очень пространственный формат файла).
Мой код С# делает что-то вроде этого:
StringBuilder sb = new StringBuilder( expectedCharacterCount );
int idxInBits = 0;
Boolean[] bits = ...;
for(int i = 0; i < someLength; i++) {
Char c = ReadNextCharacter( ref idxInBits, 6 ); // each character is 6 bits in this example
sb.Append( c );
}
В Swift я предполагаю, что NSMutableString является эквивалентом .NET StringBuilder, и я нашел этот QA о добавлении отдельных символов (Как добавить символ в строку в Swift?), поэтому в Swift у меня есть следующее:
var buffer: NSMutableString
for i in 0..<charCount {
let charValue: Character = readNextCharacter( ... )
buffer.AppendWithFormat("%c", charValue)
}
return String(buffer)
Но я не знаю, почему он сначала проходит через строку формата, что кажется неэффективным (переписывая строку формата на каждой итерации), и когда мой код работает на устройствах iOS, я хочу быть очень консервативным с моей программой Использование процессора и памяти.
Как я писал это, я узнал, что мой код действительно должен использовать UnicodeScalar вместо Character, проблема NSMutableString не позволяет вам добавить значение UnicodeScalar, вы должны использовать Swift own mutable String, поэтому теперь мой код выглядит следующим образом:
var buffer: String
for i in 0..<charCount {
let x: UnicodeScalar = readNextCharacter( ... )
buffer.append(x)
}
return buffer
Я думал, что String является неизменным, но я заметил, что его метод append возвращает Void.
Мне все еще кажется неудобным делать это, потому что я не знаю, как тип Swift String реализуется внутренне, и я не вижу, как я могу перераспределить большой буфер, чтобы избежать перераспределения (если Swift String использует растущее алгоритм).