Да, но это своего рода карусель и потенциально опасно
Вот что вы делаете:
NSString *veryLargeString = ...;
NSUInteger startingIndex = ...;
NSData *veryLargeStringData = [veryLargeString dataUsingEncoding:NSUTF8StringEncoding];
const void *bytes = [veryLargeStringData bytes];
const void *subBytes = bytes + startingIndex;
NSUInteger subLength = [veryLargeStringData length] - startingIndex;
NSString *substring = [[NSString alloc] initWithBytesNoCopy:subBytes length:subLength encoding:NSUTF8StringEncoding freeWhenDone:NO];
Что это делает:
- Получается очень большая строка в виде серии байтов; Я довольно уверен, что это на самом деле не копирует байты, но обязательно используйте инструменты для проверки. Если вы можете получить эту сверхдлинную строку как
NSData
вместо NSString
, тогда вы можете быть намного увереннее, что ничего не скопировать.
- Получить фактический буфер байтов из
NSData
- Индексировать в байтовый буфер, используя некоторую арифметику указателей
- Выясните, сколько осталось буфера
- Создайте новый
NSString
с байтовым буфером, но указав NOT скопировать байты и NOT освободить буфер, когда NSString
освобожден
Итак, почему это опасно? По сути, если байтовый буфер исчезает из-под NSStrings
, могут произойти плохие вещи (вероятно, сбой).
Однако, если вы сообразительны в этом, это позволит вам создавать подстроки без копирования базовых байтов.
Коварная мысль :
Вы можете сделать veryLargeString
оставшимся связанным объектом на substring
(то есть, по сути, сделать substring
владельцем veryLargeString
). Это гарантирует, что veryLargeString
живет по крайней мере столько же, сколько substring
. Вы бы сделали это так:
static char ParentStringKey;
objc_setAssociatedObject(substring, &ParentStringKey, veryLargeString, OBJC_ASSOCIATION_RETAIN);
Когда substring
освобождается, он также автоматически освобождает свое удержание на veryLargeString
.