Проверьте, содержится ли экземпляр NSString в NSArray - PullRequest
75 голосов
/ 28 апреля 2011

У меня есть массив с кучей строк, и я хочу проверить, содержится ли определенная строка в массиве. Если я использую сообщение containsObject: в массиве, я получаю правильные результаты. Все ли NSString объекты с одинаковой строкой указывают на один и тот же объект? Или почему containsObject: работает?

NSArray *stringArray = [NSArray arrayWithObjects:@"1",@"2",@"3",anotherStringValue, nil];
if([stringArray containsObject:@"2"]){
  //DO SOMETHING
}

Ответы [ 3 ]

168 голосов
/ 28 апреля 2011

Да, жестко запрограммированные строки NSS (строковые литералы) (т. Е. Любые @"..." в вашем исходном коде) превращаются в строки, которые существуют бесконечно, пока ваш процесс работает.

Однако NSArray * containsObject: вызывает методы isEqual: для своих объектов, следовательно, даже динамически созданная строка , такая как [NSString stringWithFormat:@"%d", 2] , вернет YES в вашем примере фрагмента.
Это связано с тем, что метод NSString isEqual: (или, точнее, его isEqualToString:) реализован так, что он осведомлен о содержимом (вместо сравнения идентификаторов указателей) и, таким образом, возвращает YES для любой пары строк, содержащих очень одинаковая последовательность символов (во время сравнения), независимо от того, как и когда они были созданы.

Чтобы проверить идентичность (указатель), вам нужно перечислить ваш массив и сравнить с помощью

NSString *yourString = @"foo";
BOOL identicalStringFound = NO;
for (NSString *someString in stringArray) {
    if (someString == yourString) {
        identicalStringFound = YES;
        break;
    }
}

(что вам, скорее всего, не хотелось бы).

Или более удобным способом:

BOOL identicalStringFound = [stringArray indexOfObjectIdenticalTo:someString] != NSNotFound;

(вы, скорее всего, тоже этого не захотите).


Подводя итог:

Таким образом, причина, по которой вы получаете положительный ответ от containsObject:, заключается в НЕ , потому что литеральные строки совместно используют один и тот же константный экземпляр, НО , потому что containsObject: по соглашениям isEqual:, который осведомлен о содержании.

Возможно, вы захотите прочитать (краткую) документацию для isEqual: из протокола NSObject .

17 голосов
/ 28 апреля 2011

containsObject: выполняет проверку значения, а не указатель. Он использует метод isEqual:, определенный NSObject и переопределенный другими объектами для тестирования. Следовательно, если две строки содержат одинаковую последовательность символов, они будут считаться одинаковыми.

В некоторых случаях очень важно различать тестирование указателя и тестирование значения. Константные строки, определенные в исходном коде, объединяются компилятором так, что они являются одним и тем же объектом. Однако строки, создаваемые динамически, не являются одним и тем же объектом. Вот пример программы, которая продемонстрирует это:

int main(int argc, char **argv) {
    NSAutoreleasePool *p = [NSAutoreleasePool new];
    NSString *constantString = @"1";
    NSString *constantString2 = @"1";
    NSString *dynamicString = [NSString stringWithFormat:@"%i",1];
    NSArray *theArray = [NSArray arrayWithObject:constantString];
    if(constantString == constantString2) NSLog(@"constantString == constantString2");
        else NSLog(@"constantString != constantString2");
    if(constantString == dynamicString) NSLog(@"constantString == dynamicString");
        else NSLog(@"constantString != dynamicString");
    if([constantString isEqual:dynamicString]) NSLog(@"[constantString isEqual:dynamicString] == YES");
        else NSLog(@"[constantString isEqual:dynamicString] == NO");
    NSLog(@"theArray contains:\n\tconstantString: %i\n\tconstantString2: %i\n\tdynamicString: %i",
          [theArray containsObject:constantString],
          [theArray containsObject:constantString2],
          [theArray containsObject:dynamicString]);
}

Вывод этой программы:

2011-04-27 17: 10: 54,686 a.out [41699: 903] constantString == constantString2
2011-04-27 17: 10: 54.705 a.out [41699: 903] constantString! = DynamicString
2011-04-27 17: 10: 54.706 a.out [41699: 903] [constantString isEqual: dynamicString] == ДА
2011-04-27 17: 10: 54.706 a.out [41699: 903] theArray содержит:
constantString: 1
constantString2: 1
dynamicString: 1

3 голосов
/ 22 мая 2018

Вы можете использовать containsObject, чтобы узнать, существует ли определенная строка,

NSArray *stringArray = [NSArray arrayWithObjects:@"1",@"2",@"3",anotherStringValue, nil];

if ( [stringArray containsObject: stringToFind] ) {
    // if found
} else {
    // if not found
}
...