the*_*tic 0 singleton objective-c nsmutabledictionary ipad
我有一个单例类,我设置了一个NSMutableDictionary被调用的completedLevels.
这是我设置的init方式(在我的单身人士的方法中):
NSString *mainPath = [[NSBundle mainBundle] bundlePath];
NSString *levelConfigPlistLocation = [mainPath stringByAppendingPathComponent:@"levelconfig.plist"];
NSDictionary *levelConfig = [[NSDictionary alloc] initWithContentsOfFile:levelConfigPlistLocation];
completedLevels = [[NSMutableDictionary alloc]init];
NSMutableDictionary *levelSets = [[NSMutableDictionary alloc]init];
NSMutableDictionary *levels = [[NSMutableDictionary alloc]init];
NSMutableDictionary *stats = [[NSMutableDictionary alloc]init];
[stats setObject:[NSNumber numberWithBool:NO] forKey:@"levelDone"];
[stats setObject:[NSNumber numberWithInt:0] forKey:@"stars"];
[stats setObject:[NSNumber numberWithInt:0] forKey:@"time"];
[stats setObject:[NSNumber numberWithInt:0] forKey:@"bestTime"];
for (int i = 1; i<=18; i++) {
[levels setObject:stats forKey:[NSString stringWithFormat:@"level%d", i]];
}
for(int i= 1; i<=15;i++){
NSString *lvlSet = [NSString stringWithFormat:@"levelSet%d", i];
[levelSets setObject:levels forKey:lvlSet];
}
NSArray *categoriesArray = [levelConfig objectForKey:@"categoriesArray"];
for (int i=0; i<[categoriesArray count]; i++) {
NSString *category = [[levelConfig objectForKey:@"categoriesArray"]objectAtIndex:i];
[completedLevels setObject:levelSets forKey:category];
}
Run Code Online (Sandbox Code Playgroud)
我想解释一下我的行为:
我的意图是以这种形式创建一个字典:
category = {
levelSet1 ={
level1 ={
bestTime = 0;
levelDone = 0;
stars = 0;
time = 0;
};
level2={
bestTime = 0;
levelDone = 0;
stars = 0;
time = 0;
};
.
.
.
}
levelSet2 ={
level1 ={
bestTime = 0;
levelDone = 0;
stars = 0;
time = 0;
};
level2={
bestTime = 0;
levelDone = 0;
stars = 0;
time = 0;
};
.
.
.
}
.
.
.
}
Run Code Online (Sandbox Code Playgroud)
levelSet的%d是1到15之间的整数.
在级别的情况下,%d是从1到18的整数.
我有几个类别,因此上面的例子有多组.
这很好用,在调用NSLog时,字典会出现在我的控制台中.但是,当我想要更改字典中的某些条目时,会出现问题,如下例所示:
NSString *category = [[GameStateSingleton sharedMySingleton]getCurrentCategory];
NSString *levelSet = [NSString stringWithFormat:@"levelSet%d",[[GameStateSingleton sharedMySingleton]getSharedLevelSet]];
NSNumber *currentLevel = [NSNumber numberWithInt:[[GameStateSingleton sharedMySingleton]getSharedLevel]];
NSString *levelString = [NSString stringWithFormat:@"level%d", [currentLevel intValue]];
NSMutableDictionary *categories = [[NSMutableDictionary alloc]initWithDictionary:
[[GameStateSingleton sharedMySingleton]getCompletedLevels]];
[[[[categories objectForKey:category]objectForKey:levelSet]objectForKey:levelString]setObject:[NSNumber numberWithBool:YES] forKey:@"levelDone"];
[[GameStateSingleton sharedMySingleton]setCompletedLevels:categories];
NSLog(@"%@",[[GameStateSingleton sharedMySingleton]getCompletedLevels]);
Run Code Online (Sandbox Code Playgroud)
解释一下:
当玩家完成关卡时,我希望该levelDone条目更改其值.但是当我之后记录它时levelDone,所有类别的所有条目突然变为BOOLEAN值1.为什么会这样?
-------------------更新-----------------------
completedLevels = [[NSMutableDictionary alloc]init];
NSMutableDictionary *levelSets = [[NSMutableDictionary alloc]init];
NSMutableDictionary *levels = [[NSMutableDictionary alloc]init];
NSMutableDictionary *stats = [[NSMutableDictionary alloc]init];
[stats setObject:[NSNumber numberWithBool:NO] forKey:@"levelDone"];
[stats setObject:[NSNumber numberWithInt:0] forKey:@"stars"];
[stats setObject:[NSNumber numberWithInt:0] forKey:@"time"];
[stats setObject:[NSNumber numberWithInt:0] forKey:@"bestTime"];
for (int i = 1; i<=18; i++) {
NSMutableDictionary *statsCopy = [stats mutableCopy];
[levels setObject:statsCopy forKey:[NSString stringWithFormat:@"level%d", i]];
[statsCopy release];
}
for(int i= 1; i<=15;i++){
NSString *lvlSet = [NSString stringWithFormat:@"levelSet%d", i];
NSMutableDictionary *levelsCopy = [levels mutableCopy];
[levelSets setObject:levelsCopy forKey:lvlSet];
[levelsCopy release];
}
NSArray *categoriesArray = [levelConfig objectForKey:@"categoriesArray"];
for (int i=0; i<[categoriesArray count]; i++) {
NSString *category = [[levelConfig objectForKey:@"categoriesArray"]objectAtIndex:i];
NSMutableDictionary *levelSetsCopy = [levelSets mutableCopy];
[completedLevels setObject:levelSetsCopy forKey:category];
[levelSetsCopy release];
}
Run Code Online (Sandbox Code Playgroud)
我检索和设置它的部分保持不变...
__ _ __ _ __ _ __ _ __ _ __ 解决方案 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ____
NSMutableDictionary *mutableCopy = (NSMutableDictionary *)CFPropertyListCreateDeepCopy(kCFAllocatorDefault, (CFDictionaryRef)originalDictionary, kCFPropertyListMutableContainers);
Run Code Online (Sandbox Code Playgroud)
我用这种方法做了很多副本.
基本上,问题是您要将每个级别的级别字典设置为相同的stats对象:
for (int i = 1; i<=18; i++) {
[levels setObject:stats forKey:[NSString stringWithFormat:@"level%d", i]];
}
Run Code Online (Sandbox Code Playgroud)
相反,您需要将它们设置为对象的不同可变副本:
for (int i = 1; i<=18; i++) {
NSMutableDictionary *statsCopy = [stats mutableCopy];
[levels setObject:statsCopy forKey:[NSString stringWithFormat:@"level%d", i]];
[statsCopy release];
}
Run Code Online (Sandbox Code Playgroud)
那应该为你解决第一部分.但是,levelSets也存在同样的问题.基本上,每当你添加一个可变字典时,你需要确定你是否试图指向同一个可变对象(你想让它们保持同步),或者你是否想要那个可变对象的副本(因此,它们独立地行动).当你看到构建这种树形结构时,这意味着你需要在每个层面上看这个.
因此,查看其余代码,您还需要以相同的方式修复级别集和类别,方法是在每个循环内部创建一个可变副本,然后添加该可变副本而不是添加原始对象.并且,由于您想要改变字典内容的内容,每次制作包含另一个可变字典的可变副本时,您需要在每个深度制作该副本.
您将不得不在深度构建这些东西或进行深层复制之间做出选择.还有一个问题:
NSMutableDictionary的深度可变副本
很好地涵盖了可变字典的深层副本.或者,您可以反转结构的构建,以便构建每个字典而不是复制,除了stats您可以轻松复制.
深拷贝会创建每个可变条目的副本,一直到最远的叶节点.如果您将NSMutableDictionaries视为一个树,其顶部是树的基础(在您的情况下为completedLevels),而叶子是您复制的统计数据NSMutableDictionaries的元素,则您希望单独操作树的每个元素,它是叶节点或任何中间节点.
可以如下进行说明,其中表示以下内容MyDictionary:
Top-A:
Second-A-1
Second-A-2
Top-B:
Second-B-1
Second-B-2
Run Code Online (Sandbox Code Playgroud)
回顾一下,你有MyDictionary顶部,它有2个键(Top-A,Top-B),每个键与一个单独的NSMutableDictionary对象相关联.每个NSMutableDictionaries都有2个键,每个键与一个单独的对象相关联.
当你创建一个-mutableCopy时MyDictionary,结果是一个NSMutableDictionary带有2个键(Top-A,Top-B)的新键,每个键与NSMutableDictionary相关联. 但是,这些NSMutableDictionary对象实际上与其中的对象相同MyDictionary.这是一个浅表副本,意味着有一个新的顶级对象(可变副本MyDictionary),但与新词典中每个键相关联的对象与键中的对象相同MyDictionary.因此,如果您更改Top-A的副本与其他副本相关联NSMutableDictionary,则Top-Ain MyDictionary和副本将不再相同.但是,如果更改与之关联的值Second-A-1,它将同时更改单个对象MyDictionary的MyDictionary因果Top-A点副本.
当你做一个深拷贝,该程序会将单独的每个字典的每一个元素,这意味着该副本MyDictionary将有一个单独的Top-A,Second-A-1,Second-A-2,Top-B,等从存在于那些MyDictionary,因此,你可以改变的任何值字典(无论多深),不用担心改变其他物体.
| 归档时间: |
|
| 查看次数: |
667 次 |
| 最近记录: |