Проверить, содержится ли экземпляр NSString в NSArray

#cocoa #nsstring #nsarray

#cocoa #nsstring #nsarray

Вопрос:

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

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

Ответ №1:

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

Однако методы containsObject: NSArray 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: , ЗАКЛЮЧАЕТСЯ НЕ в том, что литеральные строки совместно используют один и тот же экземпляр constant, А containsObject: в том, что isEqual: по соглашению вызывает, что является content aware.

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

Ответ №2:

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:ntconstantString: %intconstantString2: %intdynamicString: %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 равнозначен:dynamicString] == ДА
2011-04-27 17:10: 54.706 a.out[41699:903] Массив содержит:
constantString: 1
constantString2: 1
dynamicString: 1

Ответ №3:

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

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

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