【问题标题】:Different Keys Point to Same Object(s) in NSMutableDictionaryNSMutableDictionary 中不同的键指向相同的对象
【发布时间】:2011-01-12 02:30:50
【问题描述】:

我有一个名为Person 的自定义对象,其中包含一个名为descriptorNSString 字段,它存储Person 对象的类型(愤怒、悲伤、狂野、快乐、忧郁、 ETC)。我所有的 Person 对象都在 NSMutableArray 中,但我想以这种方式将它们存储在 NSMutableDictionary 中:

键:A,对象:一个NSMutableArray,其中所有Person 对象都有以“A”开头的descriptor

键:B,对象:一个NSMutableArray,其中所有Person 对象都有descriptor 以“B”开头

键:C,对象:一个NSMutableArray,其中所有Person对象都有descriptor以'C'开头 等等……

我尝试在下面的代码中执行此操作,并且在注释 //POINT 1 中,键和数组似乎匹配,但在 //POINT 2,当我打印出完整的字典时,所有键得出相同的值!

所以我想知道为什么我似乎拥有的NSMutableArray 没有按照我想要的方式存储在NSMutableDictionary 中?

- (void)buildDictionaryForIndexList {
    NSMutableDictionary *tempDict = [[[NSMutableDictionary alloc] init] autorelease];
    NSMutableArray *personsStartingWithLetter = [[NSMutableArray alloc] init];
    NSMutableArray *indexList = [[[NSMutableArray alloc] init] autorelease];
    NSInteger loopCounter = 1;
    NSString *firstLetter = [[[NSString alloc] init] autorelease];
    for (Person *v in persons) {
        firstLetter = [[v descriptor] substringWithRange:NSMakeRange(0, 1)];
        if ([indexList containsObject:firstLetter]) {
            [personsStartingWithLetter addObject:v];
            if (loopCounter == [persons count]) {
                [tempDict setObject:personsStartingWithLetter forKey:firstLetter];
            }
        } else {
            if (loopCounter > 1) {
                //POINT 1
                NSLog(@"%@",[indexList objectAtIndex:[indexList count]-1]);
                for (Person *q in personsStartingWithLetter) {
                    NSLog(@"%@",[q descriptor]);
                }
                [tempDict setObject:personsStartingWithLetter forKey:[indexList objectAtIndex:([indexList count] - 1)]];
                [personsStartingWithLetter removeAllObjects];
            }
            [indexList addObject:firstLetter];
            [personsStartingWithLetter addObject:v];
        } // else
        loopCounter++;
    } // for
     //POINT 2
    NSEnumerator *enumerator = [tempDict keyEnumerator];
    for (NSString *str in enumerator) {
        NSLog(@"%@",str);
        for (Person *c in [tempDict objectForKey:str]) {
            NSLog(@"%@",[c descriptor]);
        }
    }
    self.dictionary = tempDict;
} // buildDictionaryForIndexList

因此,例如,在第 1 点,我的输出是:

一个

生气

和蔼可亲

B

好战的

C

...

W

狂野

但在第 2 点我的输出是

T

狂野

J

狂野

一个

狂野

...

W

狂野

【问题讨论】:

  • 提醒我你为什么要这么做[[[NSString alloc] init] autorelease]?没有帮手吗?喜欢-string
  • 事实上,你为什么在那个方法中使用autorelease?这些对象的生命周期仅限于该方法,因此您不妨在方法结束时向它们发送-release 消息。
  • @Jacob Relkin:将其归咎于糟糕的内存管理方式。但是,假设我改变了所有这些(并且我已经改变了),我仍然遇到同样的问题。

标签: objective-c xcode nsmutablearray nsmutabledictionary


【解决方案1】:

[tempDict setObject:personsStartingWithLetter forKey:[indexList objectAtIndex:([indexList count] - 1)]];(就在第 1 点之后)更改为 [tempDict setObject:[[personsStartingWithLetter copy] autorelease] forKey:[indexList objectAtIndex:([indexList count] - 1)]];。问题是 NSDictionary 复制了键,但保留了值。因此,如果将可变数组添加到字典中,然后对其进行更改,则字典中的数组也会更改。您需要创建数组的非可变副本以放入字典中。

【讨论】:

    【解决方案2】:

    整个方法有点过于复杂。

    - (void)buildDictionaryForIndexList 
    {
        NSMutableDictionary *tempDict = [[[NSMutableDictionary alloc] init] autorelease];
        for (Person *v in persons)
        {
            NSString* firstLetter = [[v descriptor] substringWithRange:NSMakeRange(0, 1)];
            NSMutableArray* personsStartingWithLetter = tempDict [firstLetter];
            if (personsStartingWithLetter == nil)
            {
                personsStartingWithLetter = [NSMutableArray array];
                tempDict [firstLetter] = personsStartingWithLetter;
            }
            [personsStartingWithLetter addObject:v];
        } // for
        self.dictionary = tempDict;
    }
    

    您从一个包含数组的空字典开始。对于每个人,您检查是否有合适的数组,如果没有,则创建它。所以现在一个人的数组,所以你将它添加到数组中。就这样。

    【讨论】:

      猜你喜欢
      • 2016-09-26
      • 1970-01-01
      • 2019-05-13
      • 2017-04-10
      • 1970-01-01
      • 1970-01-01
      • 2021-01-21
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多