2012-02-06 3 views
1

Можно создать дубликат:
Understanding NSString comparison in Objective-CПочему NSString иногда работает с знаком равенства?

просто читал до о равенстве против личности, и я понял, что я использовал некоторые одинаковые знаки при сравнении строк в моем ObjC коде. Странно то, что он действительно работает от времени до времени, и мне было интересно, почему.

http://www.karlkraft.com/index.php/2008/01/07/equality-vs-identity/

У меня есть два фрагмента кода, одну работу и один не делает.

РАБОТА. Здесь у меня есть объект под названием «Категория», который имеет свойство NSString, называемое «имя».

@property (nonatomic, retain) NSString *name; 

Я тогда функция, где я прохожу в указателе марки «КАТЕГОРИИ» и, когда я использую знак равенства здесь, он прекрасно работает.

-(void)addCategoryToStorage:(Category*)newcategory { 
     if(newcategory.name != @"All") { // this works 

НЕ РАБОТАЕТ. Здесь я использую вывод вызова NSFileManager;

NSArray *dirContent = [self.fileManager 
         contentsOfDirectoryAtPath:@"MyFiles" 
         error:nil]; 

я пытаюсь сравнить с из NSStrings в массиве:

for(int i = 0; i < [dirContent count]; i++) { 
    if([dirContent objectAtIndex:i] == @"MyFile") // This will never be True 

Так мои вопросы в том, что бы быть причиной, почему эти два указателя NSString будет работать так, по-другому? Я знаю, что я не должен использовать «==», но на данный момент, но мне просто интересно, почему это работает иногда.

Я заметил некоторую разницу между их отладкой. В первом случае имя «newcategory» указано «(__NSCFConstantString *) и имеет значение видимое. По какой-то причине массивы «dirContent» содержат два объекта (__NSString *), где значения не видны.

Возникает другой вопрос. Что делает NSString в первом случае стать константой? Кажется, что-то связано с тем, как он создается, когда я передаю его функции. Когда я выделяю новый объект с свойством NSString, который затем передаю функции, функция видит его константой (свойство NSString объекта). Но когда объект хранится в списке, и я его захватываю, передавая [array objectAtIndex: index] в функцию, функции не получают его как константу (свойство NSString объекта).

Спасибо!

ответ

5

Это может сработать, когда указатели указывают на один и тот же объект.

Если у вас есть строковый литерал в коде, это фактически статически выделенный объект типа NSString. В любой точке вашего кода, если вы ссылаетесь на это строковое значение, вы фактически используете один и тот же указатель. (Указатель - это в основном адрес памяти)

Если у вас есть строковый литерал @"abc" в более чем одной точке вашего кода, компилятор помещает только один экземпляр и использует указатель на этот единственный экземпляр.

Это объясняет, почему @"abc" == @"abc".

Берем пример:

if(newcategory.name != @"All") 

будет работать только тогда, когда в какой-то момент в коде вы сделали:

newcategory.name = @"All"; 

И будет не работать, если вы могли бы сделать:

newcategory.name = [NSString stringWithFormat:@"%c%c%c",'A','l','l']; 

потому что в этом последнем случае вы явно выделите новую строку.

редактировать просто проверял, этот пример был испорчен:

newcategory.name = [NSString stringWithString:@"All"]; 

, потому что это оптимизировано далеко, так что вы будет иметь один и тот же указатель на @"All"

+3

Технический термин: * string interning *. –

+1

Итак, компилятор не будет иметь никакого значения между [NSString stringWithString: @ "All"] и @ "All"? – chikuba

+0

А как насчет того, как компилятор делает строку в константе в некоторых случаях? У меня есть две функции, где я предоставляю ему указатель категории, а иногда NSString является константой. – chikuba

0

Когда вы сравниваете с ==, вы не сравниваете сами строки, вы сравниваете значения указателей со строками. Когда вы объявляете строковые литералы в своем коде, они сохраняются в data segment вашего исполняемого файла. Если более чем одна строковая переменная указывает на один и тот же строковый литерал, они могут указывать на одно и то же место памяти.

Когда вы загружаете строку из файла, указатели не могут быть равны, поскольку они не могли бы произойти из сегмента данных исполняемого файла.

Например, два строковых литерала asdf часто будут храниться только один раз в исполняемом файле, поэтому значения указателей будут равны.Это оптимизация, выполняемая компилятором, хотя и не всегда будет работать.

NSString* someVariable = @"asdf"; 

if(someVariable == @"asdf") 
    NSLog(@"They are equal!"); 
0

NString ВСЕГДА работает с «== msgstr "знак, если вы хотите сравнить два указателя, чтобы увидеть, ссылаются ли они на объект EXACT SAME.

И короткие литералы обычно объединены таким образом, что, вероятно, @ "ABC" == @ "ABC", даже если один из этих литералов находится в другом классе.

Но не рассчитывайте на это.

+0

Я знаю об этом.Atm Я хотел бы знать, какая самая большая разница между двумя моими NSStrings, а также почему компилятор превращает строки свойств объекта в const в некоторых случаях. – chikuba

+1

Есть некоторые тайны, которые лучше оставить неизвестными. ;) (На самом деле, я не понимаю всех деталей, но в Objective-C объект, подобный NSString, может быть одним из нескольких разных базовых классов, в зависимости от того, как именно он был создан. Однако не имеет значения, поскольку NSString всегда * постоянно *, и он будет корректно отвечать всем соответствующим методам/селекторам независимо от его базового класса.) –

Смежные вопросы