2011-11-08 8 views
6


Desidero avere un semplice NSSet che viene caricato con alcuni NSNumbers e quindi scoprire se quei numeri sono già stati aggiunti o meno nell'insieme. Quando faccio questo:NSSet of NSNumbers - il metodo membro è sempre nil

NSMutableSet *set = [[NSMutableSet alloc] init]; 
NSNumber *num1 = [NSNumber numberWithInt:5]; 
NSNumber *num2 = [NSNumber numberWithInt:5]; 
[set addObject:num1]; 
if([set member:num2]){ 
    // something... 
} 

Il problema è che il membro restituisce sempre nullo (se è false), anche se quei numeri sono gli stessi. Il metodo isEqual restituisce true. Così

if([num1 isEqual:num2]){ 
    // correct 
} 

opere ...
in Documenti Ho letto che il metodo utente utilizza IsEqual quindi non so quale sia il problema ... Grazie per qualsiasi consiglio.

+0

se il codice è stato incollato correttamente - non hai aggiunto l'oggetto num2 al tuo set – Maggie

+0

sei sicuro ... il tuo codice funziona perfettamente bene per me! – Devarshi

+0

@Maggie sì, sono sicuro, il punto è che voglio controllare se il numero 5 è già nel set, ma devo usare nsnumber perché sono oggetti, quindi voglio controllare se l'oggetto nsnumber con valore di 5 è già nel set (num1 con valore 5 è, quindi dovrebbe restituire true) – haluzak

risposta

2

Il problema è che si sta verificando se num1 e num2 sono lo stesso oggetto. E loro non lo sono. Hanno solo lo stesso valore ma sono due oggetti diversi con lo stesso valore.

Quindi quello che state verificando con member è se hanno lo stesso indirizzo in memoria.

Modifica: è necessario utilizzare compare per verificare se i valori dei numeri sono uguali!

+0

"se hanno lo stesso indirizzo nella memoria "non è vero; secondo il membro: 'docs:" Se il set contiene un oggetto uguale all'oggetto (come determinato da isEqual :) allora quell'oggetto (tipicamente questo sarà oggetto), altrimenti niente. " – Wevah

+0

Potresti avere entrambi ragione ...Mi sembra di ricordare che NSNumber ha una subdolo ottimizzazione in cui ha le rappresentazioni statiche dei primi numeri interi. In questo caso l'indirizzo di memoria _e_ isEqual funzionerebbe. – jrturton

+0

Certo, ma non dovrebbe restituire falso in entrambi i casi. – Wevah

4

È necessario confrontare i valori dei NSNumbers, non gli oggetti.

È possibile utilizzare objectsPassingTest:

Esempio:

NSMutableSet *set = [[NSMutableSet alloc] init]; 
NSNumber *num1 = [NSNumber numberWithInt:5]; 
NSNumber *num2 = [NSNumber numberWithInt:5]; 
NSNumber *num3 = [NSNumber numberWithInt:3]; 
[set addObject:num1]; 

NSSet *filteredSet; 
filteredSet = [set objectsPassingTest:^(id obj,BOOL *stop){ 
    return [obj isEqualToNumber:num2]; 
}]; 
NSLog(@"Contains num2: %@", (filteredSet.count == 1) ? @"YES" : @"NO"); 

filteredSet = [set objectsPassingTest:^(id obj,BOOL *stop){ 
    return [obj isEqualToNumber:num3]; 
}]; 
NSLog(@"Contains num3: %@", (filteredSet.count == 1) ? @"YES" : @"NO"); 

NSLog uscita:

Contains num2: YES 
Contains num3: NO 

Oppure, se utilizza predicati si desidera:

filteredSet = [set filteredSetUsingPredicate:[NSPredicate predicateWithFormat:@"SELF == %@", num2]]; 
NSLog(@"Contains num2: %@", (filteredSet.count == 1) ? @"YES" : @"NO"); 

filteredSet = [set filteredSetUsingPredicate:[NSPredicate predicateWithFormat:@"SELF == %@", num3]]; 
NSLog(@"Contains num3: %@", (filteredSet.count == 1) ? @"YES" : @"NO"); 
2

Il merluzzo e lavora dal Ciao parola viene scritto nel registro quando l'eseguo

NSMutableSet *set = [[NSMutableSet alloc] init]; 
NSNumber *num1 = [NSNumber numberWithInt:5]; 
NSNumber *num2 = [NSNumber numberWithInt:5]; 
[set addObject:num1]; 
if([set member:num2]){ 
    NSLog(@"Hello, world"); 
    } 
+0

Questo non è abbastanza valido poiché se cambio il valore di * num1 a 6 dopo averlo aggiunto al set e poi chiedere è [imposta membro num1] e [imposta membro num2] entrambi restituiscono true. –

+0

@RyanHeitner, Come è possibile modificare un oggetto NSNumber? Sono immutabili! – ragnarius

+0

NSNumber * num1 = [NSNumber numberWithInt: 5]; [imposta addObject: num1]; num1 = [NSNumber numberWithInt: 6]; –

4

Quando si utilizza NSArray è necessario confrontare i valori invece che gli oggetti stessi. Invece di utilizzare NSArray, è possibile utilizzare NSMutableIndexSet. Questo ti permette di confrontare i valori con pochi passaggi in meno.

//during init, add some numbers 
NSMutableIndexSet *tSet = [[NSMutableIndexSet alloc] init]; 
NSUInteger exampleValue = 7; 
[tSet addIndex:exampleValue]; 
exampleValue = 42; 
[tSet addIndex:exampleValue]; 

//...later on 
//look to see if numbers are there 
if ([tSet containsIndex:7]){ 
    NSLog(@"7 exists!"); 
} 
if ([tSet containsIndex:8]){ 
    NSLog(@"8 exists!"); 
} 

Uscita: 7 esiste!

Problemi correlati