Манипуляции со строками без утечек памяти? - PullRequest
5 голосов
/ 10 февраля 2009

Я бы хотел выполнить серию подстановок строк для удаленных символов, таких как '&'.

1) Существует ли существующая функция UIKit, которая может сделать это?

2) Если нет, как лучше всего это сделать без утечки памяти? Вот идея:

-(NSString*) unescape:(NSString*)string
{
    string = [string stringByReplacingOccurrencesOfString:@"'" withString:@"'"];
    string = [string stringByReplacingOccurrencesOfString:@"&" withString:@"&"];
    string = [string stringByReplacingOccurrencesOfString:@""" withString:@"\""];
    string = [string stringByReplacingOccurrencesOfString:@">" withString:@">"];
    string = [string stringByReplacingOccurrencesOfString:@"&lt;" withString:@"<"];
    return string;
}

Но не утечка памяти при каждом назначении? Или stringByReplacingOccurferencesOfString возвращает автоматически освобожденные строки? Как мы подтверждаем, что строки stringByReplacingOccurferencesOfString автоматически высвобождаются? Или мы должны обернуть их [... autorelease]?

Даже если они автоматически выпущены, предпочтительнее избегать автоматического выпуска на iPhone. (См. здесь ). Итак, мы бы сделали:

-(NSString*) unescape:(NSString*)string
{
    NSString* string2 = [string stringByReplacingOccurrencesOfString:@"&apos;" withString:@"'"];
    // don't release 'string' because we didn't allocate or retain it
    NSString* string3 = [string2 stringByReplacingOccurrencesOfString:@"&apos;" withString:@"'"];
    [string2 release];
    NSString* string4 = [string3 stringByReplacingOccurrencesOfString:@"&apos;" withString:@"'"];
    [string3 release];
    //...and so on
}     

Но это довольно уродливый код. Какой лучший способ написать этот код, чтобы сделать несколько замен? Как бы вы это сделали?

Ответы [ 3 ]

8 голосов
/ 10 февраля 2009

Любой метод какао, который возвращает новый объект с помощью метода, который не начинается с init или содержит слово copy, возвращает объект с автоматическим освобождением. Таким образом, приведенный выше код не должен иметь утечек.

Хотя здесь может быть проще использовать NSMutableString. Затем вы просто изменяете строку на месте, а не создаете кучу автоматически выпущенных строковых объектов, что должно сделать вещи чище.

Кроме того, как насчет словаря отображений, которые вы просматриваете, находя key и заменяя value каждого элемента. Возможно, даже сохраните это в виде списка в вашем приложении для легкой настройки позже.

6 голосов
/ 10 февраля 2009

Как сказал Squeegy, все приведенные выше методы возвращают автоматически выпущенные объекты. Второй пример кода завершится сбоем, потому что вы перевыпускаете строковые объекты.

Squeegy указал один из способов справиться с этим, используя NSMutableStrings. Я бы порекомендовал такой подход. Например, следующая перезапись вашего метода:

-(NSString*) unescape:(NSString*)string
{
    NSMutableString *unescapedString = [[NSMutableString alloc] initWithString:string];
    [unescapedString replaceOccurrencesOfString:@"&apos;" withString:@"'" options:0 range:NSMakeRange(0, [unescapedString length])];
    [unescapedString replaceOccurrencesOfString:@"&amp;" withString:@"&" options:0 range:NSMakeRange(0, [unescapedString length])];
    [unescapedString replaceOccurrencesOfString:@"&quot;" withString:@"\"" options:0 range:NSMakeRange(0, [unescapedString length])];
    [unescapedString replaceOccurrencesOfString:@"&gt;" withString:@">" options:0 range:NSMakeRange(0, [unescapedString length])];
    [unescapedString replaceOccurrencesOfString:@"&lt;" withString:@"<" options:0 range:NSMakeRange(0, [unescapedString length])];
    return [unescapedString autorelease];
}

возвращает только автоматически выпущенную NSMutableString в конце.

Еще лучше было бы, если бы вы передали указатель на указатель NSMutableString (NSMutableString **). Таким образом, вы можете изменить строку, созданную вне вашего метода, без создания новой временной строки. Если это кажется странным, взгляните на методы, которые работают с экземплярами NSError.

РЕДАКТИРОВАТЬ: игнорировать мое заявление о необходимости двойного указателя в предыдущем абзаце. Как указывает erikprice, вам просто нужно передать указатель NSMutableString. Двойной указатель необходим только в том случае, если вы создаете новый экземпляр NSMutableString в своем методе для замены передаваемого, что здесь не так.

3 голосов
/ 10 февраля 2009

Рекомендую прочитать Правила управления памятью какао .

...