Проверьте, содержится ли экземпляр NSString в NSArray
у меня есть массив с кучей строк, и я хочу проверить, если определенная строка содержится в массиве. Если я использую containsObject
: сообщение на массиве, я получаю правильные результаты. Делай все NSString
объекты с одной строкой указывают на один и тот же объект? Или почему это containsObject
: работает?
NSArray *stringArray = [NSArray arrayWithObjects:@"1",@"2",@"3",anotherStringValue, nil];
if([stringArray containsObject:@"2"]){
//DO SOMETHING
}
3 ответа:
да, жестко закодированные NSStrings (строковые литералы) (то есть любые
NSArray ' s@"..."
в исходном коде) превращаются в строки, которые существуют бесконечно во время выполнения вашего процесса.containsObject:
вызовы методовisEqual:
на его объекты, поэтому даже динамически создаваемую строку например[NSString stringWithFormat:@"%d", 2]
вернутсяYES
в вашем примере фрагмента.
Это потому, что NSString вisEqual:
(точнее егоisEqualToString:
) метод реализуется, чтобы быть content aware (против сравнения идентификаторов указателей) и таким образом возвращает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.
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 содержит:
Константа: 1
constantString2: 1
dynamicString: 1