Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

NSDictionary With Integer Values

Tags:

I'm working on a game with monsters. Each one has a list of stats that are all going to be ints. I can set up each stat as it's own variable but I'd prefer to keep them in an NSDictionary since they are all related. I'm running into a problem when I'm trying to change the value's of each stat.

What I Have:

-(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; } 

What I want to do

-(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 I'm Getting

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

So it seems obvious to me that the reason I'm getting the problem is that I'm getting an object returned from objectForKey instead of an integer. So I tried to do the intValue method on the object I'm getting but that gave me another error, specifically:

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

I'm out of ideas for how to fix this. Any help? Would it be better to just give up the idea to store them all together and just use an int property for each stat?

like image 630
CaldwellYSR Avatar asked Jul 05 '12 20:07

CaldwellYSR


People also ask

How do you set a value in NSDictionary?

You have to convert NSDictionary to NSMutableDictionary . You have to user NSMutableDictionary in place of the NSDictionary . After that you can able to change value in NSMutableDictionary . Save this answer.

What is the difference between NSDictionary and NSMutableDictionary?

Main Difference is:NSMutableDictionary is derived from NSDictionary, it has all the methods of NSDictionary. NSMutableDictionary is mutable( can be modified) but NSDictionary is immutable (can not be modified).

What is NSDictionary in Objective c?

The NSDictionary class declares the programmatic interface to objects that manage immutable associations of keys and values. For example, an interactive form could be represented as a dictionary, with the field names as keys, corresponding to user-entered values.

Does NSDictionary retain objects?

An NSDictionary will retain it's objects, and copy it's keys. Here are some effects this has had on code I've worked on. Sometimes you get the same object you put in, sometimes not. Immutable objects are optimized to return themselves as a copy .


2 Answers

  1. You can only store objects, not primitives, within Cocoa collection classes, so to store numbers you need to use NSNumber objects.
  2. You need to use an NSMutableDictionary if you wish to change the contents later.
  3. Your call to dictionaryWithObjectsAndKeys has the keys and values reversed.
  4. Your stats object is not being retained, so it will be released next time round the run loop (if you're using manual reference counting, that is).

You want:

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

In order to change the values you need to create a new NSNumber object as they are immutable, so something like:

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

All pretty tedious if you ask me; there must be an easier way, for example how about creating an Objective-C class to store and manipulate this stuff?

like image 108
trojanfoe Avatar answered Nov 24 '22 01:11

trojanfoe


NSDictionarys store NSObject*s. In order to use them with integer values, you unfortunately need to use something like NSNumber. So your initialization would look like:

-(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; } 

Then you would have to retrieve them as numbers:

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

EDIT

Of course, in order to do this, self.stats needs to be an NSMutableDictionary

like image 28
Dan F Avatar answered Nov 24 '22 02:11

Dan F