NSString против NSMutableString с помощью stringByAppendingString - PullRequest
4 голосов
/ 04 марта 2011

Итак, я вполне уверен, что если я планирую часто манипулировать строками, например, с stringByAppendingString, я должен использовать переменные типа NSMutableString.

Но что, если я делаю что-то вродеthis?

UILabel *someLabel = [[UILabel alloc] init];
[someLabel setText: [[someDictionary objectForKey:@"some_key"] stringByAppendingString:@"some other string"];

Я читал, что если вы используете stringByAppendingString для строки NSString, вы получите утечки, потому что указатель, связанный с начальной строкой NSString, перемещается, указывая на новую строку, созданную добавлением,тогда как с NSMutableString ваш указатель всегда указывает на эту изменяемую строку.

Так что мой вопрос заключается в том, что происходит неявно, когда я вызываю stringByAppendingString для чего-то, что является строкой, но явно не NSString или NSMutableString?Например, в моем приведенном выше случае значение некоторого ключа в словаре.Делает ли это неправильно, и я должен делать что-то вроде ниже?

[[[NSMutableString stringWithString:[someDictionary objectForKey:@"some_key"]] stringByAppendingString:@"some other string"]]

Ответы [ 4 ]

5 голосов
/ 04 марта 2011

Я читал, что если вы используете stringByAppendingString в NSString, вы в конечном итоге получите утечки, потому что указатель, связанный с начальным NSString, перемещается, указывая на новую строку, созданную добавлением, тогда как в NSMutableString ваш указатель всегдауказывает на эту изменчивую строку.

Это звучит как совет кого-то, кто не совсем понимал, что происходит с управлением памятью.Конечно, [NSString stringByAppendingString] возвращает новую строку.Но что вы делаете с этой новой строкой, зависит от вас.Конечно, вы могли бы вызвать утечку памяти, ненадлежащим образом переназначив результат сохраненному свойству, например:

myStringProperty = [myStringProperty stringByAppendingString:@" more bits"];

Правильная форма будет использовать self, например:

self.myStringProperty = [myStringProperty stringByAppendingString:@" more bits"];

Следуйте рекомендациям по памяти какао.

Что касается словарей и других типов коллекций: относитесь к тому, что выходит из словаря, надлежащим образом, с учетом типа, который вам известен.Если вы вытащите объект, который на самом деле является строкой NSString, но попытаетесь использовать его в качестве NSMutableString, ваше приложение упадет (с «селектором не найден» или подобным).Поэтому в этом случае вам необходимо создать новую NSMutableString из NSString.

Интересное примечание: Apple решила сделать NSMutableString подклассом NSString.Что-то в этом мне кажется неразумным - если что-то выглядит неизменным, потому что оно имеет тип NSString, я хочу, чтобы оно было неизменным!(Но на самом деле это может быть NSMutableString.) Сравните это с Java, у которого есть класс String и совершенно отдельный класс BufferedString.

3 голосов
/ 04 марта 2011

-stringByAppendingString собирается вернуть вам новую строку NSString, отличную от обеих задействованных строк.Другими словами:

NSString *string3 = [string1 stringByAppendingString:string2];

string3 - это совершенно новая строка.Строка1 вообще не изменяется, ничего не происходит с ее памятью или содержимым.Человек, который сказал вам, что, вероятно, просто неправильно понял, что происходит.

[mutableString1 appendString:string2];

В этом случае mutableString1 по-прежнему указывает на тот же объект, но содержимое этого объекта было изменено, чтобы включить string2.

И последнее, о чем следует помнить: если вы используете изменяемые строки, вы должны быть осторожны, когда делитесь ссылками на них.Если вы передадите свою изменяемую строку какой-то функции, которая хранит указатель на эту изменяемую строку, а затем ваш код изменяет эту изменяемую строку в какой-то момент в будущем, другая ссылка будет указывать точно на тот же объект, что означает, что другой код увидитизменить также.Если это то, что вы хотите, отлично, но если нет, вы должны быть осторожны.

Один из способов избежать этой проблемы - объявить ваши операторы @property для NSStrings как «copy» вместо «retain».Это создаст копию изменяемой строки перед ее установкой в ​​свойстве, а метод -copy неявно даст вам не изменяемую версию, поэтому он создаст копию NSString вашей NSMutableString.

3 голосов
/ 04 марта 2011

Я всегда был фанатом [NSString stringWithFormat@"%@%@", a, b];, потому что тогда вы явно получаете новую автоматически выпущенную строку и можете правильно распоряжаться "a" и "b".

С [someDictionary objectForKey:@"some_key"] вы получите тип объекта, который был изначально помещен в этот словарь. Поэтому слепой вызов stringByAppendingString без знания того, что в этом словаре, кажется плохой идеей.

0 голосов
/ 04 марта 2011

Если вы будете следовать правилам управления памятью, все будет в порядке с помощью stringByAppendingString. В двух словах:

  1. если у вас есть объект, вам нужно в какой-то момент освободить или автоматически выпустить его.
  2. вам принадлежит объект, если вы используете метод alloc, new или copy для его создания или если вы его сохранили.

Обязательно ознакомьтесь с Правилами управления памятью Apple .

В первом примере кода в вашем вопросе вы не используете alloc, new, copy или retain ни для одной из задействованных строк NSS, поэтому вам не нужно ничего делать для ее освобождения. Если за пределами кода, который вы включили в пример, который вы используете alloc, new, copy или сохранить в любых NSStrings, вам нужно будет убедиться, что они будут выпущены позже.

...