2012-07-05 52 views
16

我的工作与怪物的游戏。每个人都有一个统计列表,这些列表都将是整数。我可以将每个属性设置为自己的变量,但我宁愿将它们保存在NSDictionary中,因为它们都是相关的。当我试图改变每个属性的值时,我遇到了一个问题。的NSDictionary一个整数

我拥有的一切:

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

我想做

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

错误,我得到什么

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

小号o在我看来很明显,我得到这个问题的原因是我得到的是从objectForKey而不是整数返回的对象。于是,我就做我得到的对象上的intValue方法,但是这给了我另一个错误,具体如下:

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

我出于对如何解决这个问题的想法。任何帮助?放弃将它们全部存储在一起并仅为每个属性使用int属性会更好吗?

回答

53
  1. 你只能在Cocoa集合类中存储对象而不是基元,因此存储您需要使用NSNumber对象的数字。
  2. 你需要的,如果你想以后更改的内容使用NSMutableDictionary
  3. 您对dictionaryWithObjectsAndKeys调用有逆转的键和值。
  4. stats对象不被保留,所以它会被释放下一次轮的运行循环(如果你使用手工引用计数,这是)。

你想:

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

为了改变你需要创建一个新NSNumber对象,因为他们不变的值,所以是这样的:

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

所有,如果你很单调乏味。问我;必须有一个更简单的方法,例如,如何创建一个Objective-C类来存储和操作这些东西?

+0

如果我正在使用ARC,我不必担心保留吗?你也是对的,这看起来有点乏味......也许我会尝试上课。 – CaldwellYSR 2012-07-05 21:22:05

+0

@CaldwellYSR是的,你是对的 - 如果你使用ARC,不需要担心'retain'。 – trojanfoe 2012-07-05 21:25:52

+0

感谢您的建议,我不知道为什么我没有想到让他们成为班级。从长远来看,它会让很多事情变得更容易。 – CaldwellYSR 2012-07-05 21:28:18

7

NSDictionary 4S店NSObject*秒。为了使用它们的整数值,你不幸需要使用类似NSNumber的东西。所以,你的初始化看起来像:

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

然后,你将不得不对它们进行检索的数字:

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

编辑

当然,为了做到这一点,self.stats需要是一个NSMutableDictionary

+0

哇我怎么完全忘了你不能改变值没有他们是可变的。一旦我检索NSNumber,我将能够添加一个整数到该NSNumber? – CaldwellYSR 2012-07-05 21:10:02

+2

“dictionaryWithObjectsAndKeys”中的值和键的顺序相反,而'stats'没有被保留。 – trojanfoe 2012-07-05 21:18:39

4

适应@ trojanfoe的回答为现代的Objective-C具有很好的语法糖:

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

,并更新值:

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