2011-11-08 7 views
6


Quiero tener un NSSet simple que está cargado con algunos NSNumbers y luego averiguar si esos números ya están agregados en el conjunto o no. Cuando hago esto:NSSet of NSNumbers - método miembro es siempre nulo

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

El problema es que el miembro siempre devuelve cero (si es falso), incluso si esos números son iguales. El método isEqual devuelve verdadero. Así

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

obras ...
En docs leí que utiliza el método miembro de IsEqual así que no sé cuál es el problema ... Gracias por cualquier consejo.

+0

si su código está pegado correctamente - no ha agregado el objeto num2 a su conjunto – Maggie

+0

está seguro ... ¡su código funciona perfectamente bien para mí! – Devarshi

+0

@Maggie sí, estoy seguro, el punto es que quiero verificar si el número 5 ya está en el conjunto, pero tengo que usar nsnumber porque son objetos, entonces quiero verificar si el objeto nsnumber con valor de 5 es Ya en el conjunto (num1 con el valor 5 es, entonces debería volver verdadero) – haluzak

Respuesta

2

El problema es que está comprobando si num1 y num2 son el mismo objeto. Y no lo son Simplemente tienen el mismo valor pero son dos objetos diferentes con el mismo valor.

Lo que está comprobando con member es si tienen la misma dirección en la memoria.

Editar: ¡Debería usar compare para verificar si los valores de los números son los mismos!

+0

"si tienen la misma dirección en la memoria "es falso; de acuerdo con 'member:' docs: "Si el conjunto contiene un objeto igual a object (según lo determinado por isEqual :), entonces ese objeto (normalmente será objeto), de lo contrario nil". – Wevah

+0

Ambos podrían tener razón ...Me parece recordar que NSNumber tiene una optimización furtiva donde tiene representaciones estáticas de los primeros enteros. En este caso, la dirección de memoria _and_ isEqual funcionaría. – jrturton

+0

Claro, pero no debe regresar falso de ninguna manera. – Wevah

4

Es necesario comparar los valores de los NSNumbers, no los objetos.

Puede utilizar objectsPassingTest:

Ejemplo:

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 de salida:

Contains num2: YES 
Contains num3: NO 

O si se desea el uso de predicados:

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

El bacalao E trabaja desde Hola palabra se escribe en el registro cuando lo ejecuto

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

Esto no es completamente válido ya que si cambio el valor de * num1 a 6 después de que lo he agregado al conjunto y luego pregunto es [set member num1] y [set member num2] ambos devuelven true. –

+0

@RyanHeitner, ¿Cómo se puede cambiar un objeto NSNumber? Ellos son inmutables! – ragnarius

+0

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

4

Cuando se utiliza NSArray es necesario comparar los valores en lugar de los objetos mismos. En lugar de usar NSArray, puede usar NSMutableIndexSet. Esto le permite comparar los valores con unos pocos pasos menos.

//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!"); 
} 

Salida: 7 existe!

Cuestiones relacionadas