2012-07-05 13 views
16

Estoy trabajando en un juego con monstruos. Cada uno tiene una lista de estadísticas que van a ser enteros. Puedo configurar cada estadística como su propia variable, pero preferiría mantenerlas en un NSDictionary ya que todas están relacionadas. Me encuentro con un problema cuando intento cambiar el valor de cada estadística.NSDictionary con valores enteros

lo que tengo:

-(id) init { 
    self = [super init]; 
    if(self) { 
     stats = [NSDictionary dictionaryWithObjectsAndKeys: 
       @"Attack", 0, 
       @"Defense", 0, 
       @"Special Attack", 0, 
       @"Special Defense", 0, 
       @"HP", 0, nil]; 
    } 
    return self; 
} 

Lo que yo quiero hacer

-(void) levelUp { 
    self.level++; 
    [self.stats objectForKey:@"Attack"] += (level * 5); 
    [self.stats objectForKey:@"Defense"] += (level * 5); 
    [self.stats objectForKey:@"Special Attack"] += (level * 5); 
    [self.stats objectForKey:@"Special Defense"] += (level * 5); 
    [self.stats objectForKey:@"HP"] += (level * 5); 
} 

error Estoy consiguiendo

Arithmetic on pointer to interface 'id', which is not a constant size in non-fragile ABI 

S o me parece obvio que la razón por la que recibo el problema es porque obtengo un objeto devuelto por objectForKey en lugar de un entero. Así que traté de hacer el método intValue en el objeto que estoy recibiendo, pero eso me dio otro error, en concreto:

Assigning to 'readonly' return result of an objective-c message not allowed 

estoy fuera de ideas sobre cómo solucionar este problema. ¿Alguna ayuda? ¿Sería mejor renunciar a la idea de almacenarlos todos juntos y simplemente usar una propiedad int para cada estadística?

Respuesta

53
  1. Usted solo puede almacenar objetos, no primitivos, dentro de las clases de colección de Cocoa, por lo que para almacenar números debe usar los objetos NSNumber.
  2. Necesita usar un NSMutableDictionary si desea cambiar los contenidos más tarde.
  3. Su llamada al dictionaryWithObjectsAndKeys tiene las claves y los valores invertidos.
  4. Su objeto stats no se conserva, por lo que se lanzará la próxima vez que se ejecute el ciclo de ejecución (si está utilizando el recuento de referencia manual, es decir).

que desee:

stats = [[NSMutableDictionary dictionaryWithObjectsAndKeys: 
    [NSNumber numberWithInt:0], @"Attack", 
    [NSNumber numberWithInt:0], @"Defense", 
    [NSNumber numberWithInt:0], @"Special Attack", 
    [NSNumber numberWithInt:0], @"Special Defense", 
    [NSNumber numberWithInt:0], @"HP", 
    nil] retain]; 

Con el fin de cambiar los valores que necesita para crear una nueva NSNumber objeto como inmutable, así que algo como:

NSNumber *num = [stats objectForKey:@"Attack"]; 
NSNumber *newNum = [NSNumber numberWithInt:[num intValue] + (level * 5)]; 
[stats setObject:newNum forKey:@"Attack"]; 

todos bastante tedioso si Pregúnteme; debe haber una manera más fácil, por ejemplo, ¿qué tal crear una clase Objective-C para almacenar y manipular esto?respuesta

+0

No tengo que preocuparme por conservar si uso ARC ¿verdad? También tienes razón esto parece un poco tedioso ... tal vez voy a probar una clase en su lugar. – CaldwellYSR

+0

@ CaldwellYSR Sí, tienes razón; no tienes que preocuparte por 'retener' si estás usando ARC. – trojanfoe

+0

Gracias por el consejo, no sé por qué no pensé en convertirlos en una clase de todos modos. Hará que muchas cosas sean más fáciles a largo plazo. – CaldwellYSR

7

NSDictionary s tienda NSObject* s. Para usarlos con valores enteros, desafortunadamente necesita usar algo como NSNumber. Por lo que su inicialización se vería así:

-(id) init { 
    self = [super init]; 
    if(self) { 
     stats = [NSDictionary dictionaryWithObjectsAndKeys: 
       @"Attack", [NSNumber numberWithInt:0], 
       @"Defense", [NSNumber numberWithInt:0], 
       @"Special Attack", [NSNumber numberWithInt:0], 
       @"Special Defense", [NSNumber numberWithInt:0], 
       @"HP", [NSNumber numberWithInt:0], nil]; 
    } 
    return self; 
} 

Entonces tendría que recuperarlos como números:

NSNumber *atk = [self.stats objectForKey:@"Attack"]; 
int iAtk = [atk intValue]; 
[self.stats setObject:[NSNumber numberWithInt:iAtk] forKey:@"Attack"]; 

EDITAR

Por supuesto, con el fin de hacer esto, self.stats necesidades de ser un NSMutableDictionary

+0

Wow ¿Cómo se me olvidó por completo que no se puede cambiar los valores sin ellos son mutables Una vez que recupere el NSNumber ¿podré agregar un número entero a ese NSNumber? – CaldwellYSR

+2

El orden de los valores y las claves en 'dictionaryWithObjectsAndKeys' se invierte y' stats' no se conserva. – trojanfoe

4

Adaptación de @ trojanfoe para los modernos de Objective-C con buen azúcar sintaxis:

stats = [@{@"Attack"   : @0, 
      @"Defense"   : @0, 
      @"Special Attack" : @0, 
      @"Special Defense" : @0, 
      @"HP"    : @0} mutableCopy]; 

Y para actualizar un valor de:

stats[@"Attack"] = @([stats[@"Attack"] intValue] + (level * 5)); 
Cuestiones relacionadas