objective c - NSDiccionario con valores enteros
objective-c int (3)
Estoy trabajando en un juego con monstruos. Cada uno tiene una lista de estadísticas que van a ser ints. Puedo configurar cada estadística como su propia variable, pero preferiría mantenerlas en un NSDictionary ya que todas están relacionadas. Me estoy topando con un problema cuando intento cambiar el valor de cada estadística.
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 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 que estoy recibiendo
Arithmetic on pointer to interface ''id'', which is not a constant size in non-fragile ABI
Por lo tanto, me parece obvio que la razón por la que tengo el problema es que estoy recibiendo un objeto devuelto por objectForKey en lugar de un entero. Así que traté de hacer el método intValue en el objeto que estoy obteniendo pero eso me dio otro error, específicamente:
Assigning to ''readonly'' return result of an objective-c message not allowed
Me quedé sin ideas sobre cómo arreglar esto. ¿Alguna ayuda? ¿Sería mejor simplemente abandonar la idea de almacenarlos todos juntos y usar una propiedad int para cada estadística?
- Solo puede almacenar objetos, no primitivos, dentro de las clases de colección de Cocoa, por lo que para almacenar números necesita usar objetos
NSNumber
. -
NSMutableDictionary
usar unNSMutableDictionary
si desea cambiar el contenido más adelante. - Su llamada a
dictionaryWithObjectsAndKeys
tiene las claves y los valores invertidos. - Su objeto de
stats
no se retiene, por lo que se lanzará la próxima vez que se realice el ciclo de ejecución (si está utilizando el recuento manual de referencias).
Usted quiere:
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];
Para cambiar los valores, debe crear un nuevo objeto NSNumber
ya que son inmutables, por lo que algo como:
NSNumber *num = [stats objectForKey:@"Attack"];
NSNumber *newNum = [NSNumber numberWithInt:[num intValue] + (level * 5)];
[stats setObject:newNum forKey:@"Attack"];
Todo bastante tedioso si me preguntas; debe haber una forma más fácil, por ejemplo, ¿qué hay de crear una clase Objective-C para almacenar y manipular estas cosas?
Adaptando la respuesta de @ trojanfoe para el moderno Objective-C con una buena sintaxis de azúcar:
stats = [@{@"Attack" : @0,
@"Defense" : @0,
@"Special Attack" : @0,
@"Special Defense" : @0,
@"HP" : @0} mutableCopy];
Y para actualizar un valor:
stats[@"Attack"] = @([stats[@"Attack"] intValue] + (level * 5));
Tienda NSDictionary
s NSObject*
s. Para poder usarlos con valores enteros, desafortunadamente necesitas usar algo como NSNumber
. Entonces tu inicialización se vería como:
-(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ías 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, para hacer esto, self.stats
debe ser un NSMutableDictionary