【问题标题】:NSDictionary With Integer Values具有整数值的 NSDictionary
【发布时间】:2012-07-06 08:08:06
【问题描述】:

我正在开发一个有怪物的游戏。每个都有一个统计数据列表,这些统计数据都将是整数。我可以将每个统计信息设置为它自己的变量,但我更愿意将它们保存在 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

所以对我来说很明显我遇到问题的原因是我得到了一个从 objectForKey 返回的对象,而不是一个整数。所以我尝试对我得到的对象执行 intValue 方法,但这给了我另一个错误,特别是:

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

我不知道如何解决这个问题。有什么帮助吗?放弃将它们全部存储在一起并为每个统计数据使用一个 int 属性的想法会更好吗?

【问题讨论】:

    标签: objective-c int nsdictionary


    【解决方案1】:

    NSDictionarys 存储 NSObject*s。为了将它们与整数值一起使用,不幸的是您需要使用类似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

    【讨论】:

    • 哇,我怎么完全忘记了如果值不可变,您就无法更改它们。检索到 NSNumber 后,我能否向该 NSNumber 添加一个整数?
    • dictionaryWithObjectsAndKeys 中的值和键的顺序颠倒了,stats 没有被保留。
    【解决方案2】:
    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 类来存储和操作这些东西怎么样?

    【讨论】:

    • 如果我使用 ARC,我不必担心保留,对吗?另外你说得对,这看起来确实有点乏味......也许我会尝试上课。
    • @CaldwellYSR 是的,您是对的 - 如果您使用 ARC,则无需担心 retain
    • 感谢您的建议,我不知道为什么我没有考虑让它们成为一个类。从长远来看,它会让很多事情变得更容易。
    • @CaldwellYSR 是的;继承和封装也会带来好处。
    【解决方案3】:

    用漂亮的语法糖来适应 @trojanfoe 对现代 Objective-C 的回答:

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

    并更新一个值:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-12-14
      • 1970-01-01
      • 2011-05-20
      相关资源
      最近更新 更多