2011-04-27 4 views
71

Ho una matrice con un gruppo di stringhe e voglio verificare se una certa stringa è contenuta nell'array. Se utilizzo il messaggio containsObject: array, ottengo risultati corretti. Tutti gli oggetti NSString con lo stesso puntatore allo stesso oggetto? O perché il containsObject: funziona?Verifica se l'istanza NSString è contenuta in un NSArray

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

risposta

156

Sì, NSStrings hard-coded (stringhe) (vale a dire qualsiasi @"..." nel codice sorgente) si trasformano in stringhe che esistono a tempo indeterminato, mentre il processo è in esecuzione.

Tuttavia NSArray s' containsObject: metodi chiama isEqual: sui suoi oggetti, quindi anche una stringa creata dinamicamente come [NSString stringWithFormat:@"%d", 2]sarebbe tornato YES nel tuo snippet campione.
Questo perché NSString di isEqual: (o più precisamente il suo isEqualToString:) metodo viene attuato essere contenuti consapevoli (vs confrontando identità puntatore) e restituisce quindi YES per ogni coppia di stringhe contenenti la stessa sequenza di caratteri (al momento confronto), non importa come e quando sono stati creati.

Per controllare per la parità (pointer-) identità che avrebbe dovuto elencare l'array e confrontare via

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

(che molto probabilmente non si vuole, però).

O in un modo più conveniente:

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

(molto probabilmente non vorrebbe questo uno o).


Riassumendo:

Quindi la ragione che stai ricevendo una risposta positiva da containsObject: è NON perché le stringhe letterali condividono la stessa istanza costante, MA perché containsObject: per convenzione chiamate isEqual: , che è consapevole del contenuto.

Si consiglia di leggere la (breve) documentazione per da NSObject protocol.

16

containsObject: esegue un controllo del valore, non un controllo del puntatore. Utilizza il metodo isEqual: definito da NSObject e sottoposto a override da altri oggetti per il test. Pertanto, se due stringhe contengono la stessa sequenza di caratteri, saranno considerate uguali.

La distinzione tra test puntatore e test del valore è molto importante in alcuni casi. Le stringhe costanti definite nel codice sorgente sono combinate dal compilatore in modo che siano lo stesso oggetto. Tuttavia, le stringhe create dinamicamente non sono lo stesso oggetto.Ecco un esempio di programma che dimostrerà questo:

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

L'output di questo programma è:

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