NSMutableDictionary 奇怪的问题

Posted

技术标签:

【中文标题】NSMutableDictionary 奇怪的问题【英文标题】:NSMutableDictionary weird problem 【发布时间】:2011-03-07 07:26:09 【问题描述】:

假设我有一个包含两个 NSMutableDictionary 的类。

@interface GameDataManager : CCNode 

    NSMutableDictionary *worldInfoDictionary;
    NSMutableDictionary *levelInfoDictionary;


@property (nonatomic, retain) NSMutableDictionary *worldInfoDictionary;
@property (nonatomic, retain) NSMutableDictionary *levelInfoDictionary;

当应用程序这样启动时,我从 plist 加载数据:

-(BOOL) readApplicationData:(NSString *)fileName

    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *documentsDirectory = [paths objectAtIndex:0];
    NSString *appFile = [documentsDirectory stringByAppendingPathComponent:fileName];
    NSData *myData = [[[NSData alloc] initWithContentsOfFile:appFile] autorelease];

    if (myData == nil) 

       return NO;
    

    NSKeyedUnarchiver *un = [[NSKeyedUnarchiver alloc] initForReadingWithData:myData];
    NSMutableDictionary *dic = [un decodeObjectForKey:@"GameData"];

    self.worldInfoDictionary = [dic objectForKey:@"WorldInfoDictionary"];
    self.levelInfoDictionary = [dic objectForKey:@"LevelInfoDictionary"];

for (int i = 1; i <= 10; i++) 

           WorldInfoData * w = [worldInfoDictionary objectForKey:
                             [[[NSString alloc] initWithFormat:@"World%d", i] autorelease]];
    NSLog(@"%d", w.worldNum);
    [w release];


    [un finishDecoding];
    [un release];
    return YES; 

在接下来的两行之后:

self.worldInfoDictionary = [dic objectForKey:@"WorldInfoDictionary"];
self.levelInfoDictionary = [dic objectForKey:@"LevelInfoDictionary"];

我可以看到两个字典中的值/键的数量是正确的。

然后我尝试打印出每个对象的所有“worldNum”值,但应用程序除外 崩溃:

2011-03-07 15:18:21.819 [1267:207] 1
2011-03-07 15:18:21.820 [1267:207] 2
2011-03-07 15:18:21.821 [1267:207] 3
2011-03-07 15:18:21.823 [1267:207] 4
2011-03-07 15:18:21.831 [1267:207] 5
2011-03-07 15:18:21.832 [1267:207] 6
2011-03-07 15:18:21.832 [1267:207] 7
2011-03-07 15:18:21.833 [1267:207] 8
2011-03-07 15:18:21.834 [1267:207] 9
2011-03-07 15:18:21.834 [1267:207] 10
Stack dump:
0.  Running pass 'Sparse Conditional Constant Propagation' on function '@gleLLVMVecProjectionTransform2'

如果我取消注释这一行:

[un release];

应用运行良好,没有崩溃。

谁能给我解释一下,非常感谢^_^

感谢大家的回答。

但是如果我删除我用来输出一些信息的代码行:

for (int i = 1; i <= 10; i++) 

           WorldInfoData * w = [worldInfoDictionary objectForKey:
                  [[[NSString alloc] initWithFormat:@"World%d", i] autorelease]];
    NSLog(@"%d", w.worldNum);
    [w release];

并取消注释“[un release];”行,readApplicationData 工作正常, 但是当我稍后尝试像这样读取数据时:

NSMutableDictionary *dic = [GameDataManager sharedGameDataManager].worldInfoDictionary;
        for (int i = 1; i <= 10; i++) 

            NSString *key = [[NSString alloc] initWithFormat:@"World%d", i];    
            WorldInfoData *worldInfoData = [dic objectForKey:key];

            if (worldInfoData.worldNum == 1) 
                //......
            
            [key release];
        

在这一行之后:“WorldInfoData *worldInfoData = [dic objectForKey:key];”,worldInfoData 的类型 不是 WorldInfoData * 而是 CCArray,因为 CCArray 没有属性 worldNum,它崩溃了......

【问题讨论】:

finishDecoding 函数里有什么? 那是NSKeyedUnarchiver的一个功能... 【参考方案1】:

首先,我建议在启用僵尸检测的情况下运行您的应用程序。

你会发现你正在过度释放 'w' 的通知。

WorldInfoData * w = [worldInfoDictionary objectForKey:
                         [[[NSString alloc] initWithFormat:@"World%d", i] autorelease]];
NSLog(@"%d", w.worldNum);
[w release];

您将“w”添加到自动释放池中,然后显式调用释放。我猜想摆脱 [w release];行将解决您的问题或不将“w”添加到自动释放池中。

【讨论】:

几乎......被明确自动释放的东西是关键。但是当w 不是此代码拥有的对象时,它会被释放。

以上是关于NSMutableDictionary 奇怪的问题的主要内容,如果未能解决你的问题,请参考以下文章

将 NSMutableDictionary 保存到 plist 问题中

从 JSON 获取的 NSData 的奇怪响应

从 plist 文件中读取字典的奇怪行为

将 NSMutableDictionary 的键/值存储到另一个 NSMutableDictionary

如何将 NSArray 添加为 NSMutableDictionary 的 NSMutableDictionary 键?

NSMutableDictionary 按顺序添加对象问题