web-dev-qa-db-fra.com

Vérifiez si l'instance NSString est contenue dans un NSArray

J'ai un tableau avec un tas de chaînes et je veux vérifier si une certaine chaîne est contenue dans le tableau. Si j'utilise le message containsObject: sur le tableau, j'obtiens des résultats corrects. Est-ce que tous les objets NSString avec la même chaîne pointent vers le même objet? Ou pourquoi le containsObject: fonctionne-t-il?

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

Oui, NSStrings codés en dur (littéraux de chaîne) (c'est-à-dire @"..." dans votre code source) sont transformées en chaînes qui existent indéfiniment pendant l'exécution de votre processus.

Cependant NSArray est containsObject: méthodes appelle isEqual: sur ses objets, donc même une chaîne créée dynamiquement telle que [NSString stringWithFormat:@"%d", 2] renverrait YES dans votre exemple d'extrait.
Ceci est dû au fait que NSString isEqual: (ou plus précisément son isEqualToString:) est implémentée pour être sensible au contenu (vs comparer les identités de pointeurs) et retourne donc YES pour toute paire de chaînes contenant la même séquence de caractères (au moment de la comparaison), peu importe comment et quand ils ont été créés.

Pour vérifier l'identité (de pointeur) égale, vous devez énumérer votre tableau et comparer via

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

(que vous ne voudriez probablement pas, cependant).

Ou d'une manière plus pratique:

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

(vous ne voudriez probablement pas non plus celui-ci).


Résumé:

Donc, la raison pour laquelle vous obtenez une réponse positive de containsObject: est [~ # ~] pas [~ # ~] car les chaînes littérales partagent la même instance constante, [~ # ~] mais [~ # ~] car containsObject: par appels conventionnels isEqual:, qui est sensible au contenu.

Vous voudrez peut-être lire la documentation (courte) pour isEqual: à partir du protocole NSObject .

168
Regexident

containsObject: effectue une vérification de valeur, pas une vérification de pointeur. Il utilise le isEqual: méthode définie par NSObject et remplacée par d'autres objets pour le test. Par conséquent, si deux chaînes contiennent la même séquence de caractères, elles seront considérées comme identiques.

La distinction entre test de pointeur et test de valeur est très importante dans certains cas. Les chaînes constantes définies dans le code source sont combinées par le compilateur afin qu'elles soient le même objet. Cependant, les chaînes créées dynamiquement ne sont pas le même objet. Voici un exemple de programme qui le démontrera:

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]);
}

Le résultat de ce programme est:

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] == OUI
2011-04-27 17: 10: 54.706 a.out [41699: 903] theArray contient:
constantString: 1
constantString2: 1
dynamicString: 1

17
ughoavgfhw

Vous pouvez utiliser containsObject pour savoir si une chaîne existe,

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

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