我正在尝试查看一个加载了NSMutableArray的NSMutableDictionary,我搞砸了,我不知道怎么做。我正在尝试加载更大的游戏问题,如果它们不是正确的级别,则删除它们。在我尝试删除之前,我没有收到错误。谁能看到这段代码中的缺陷?我非常感激!
谢谢,
〜ģ
{
NSUserDefaults *settings = [NSUserDefaults standardUserDefaults];
NSString *GameLevel = [[NSString alloc] initWithFormat: [settings objectForKey:kLevelKey]];
NSBundle *Bundle = [NSBundle mainBundle];
NSString *PListPath = [Bundle pathForResource:@"questions" ofType:@"plist"];
NSMutableDictionary *Dictionary = [[NSMutableDictionary alloc] initWithContentsOfFile:PListPath];
self.QuestionDetailsByLevel = Dictionary;
[Dictionary release];
NSMutableArray *Components = [[NSMutableArray alloc] initWithArray:[QuestionDetailsByLevel allKeys]];
self.QuestionsByLevel = Components;
int QuestionCount = [self.QuestionsByLevel count] - 1;
for (int j = 0; j < QuestionCount - 1; j++)
{
NSString *SelectedQuestion = [self.QuestionsByLevel objectAtIndex:j];
NSMutableArray *Array = [QuestionDetailsByLevel objectForKey:SelectedQuestion];
self.QDetailsByLevel = Array;
NSString *level = [[NSString alloc] initWithFormat:[self.QDetailsByLevel objectAtIndex:Level]];
if (level != GameLevel)
[QuestionsByLevel removeObjectAtIndex:j];
}
}
答案 0 :(得分:10)
除了其他人提到的其他问题之外,让我们关注你为什么会遇到越界错误。
这是相关的代码。
for (int j = 0; j < QuestionCount - 1; j++)
{
NSString *SelectedQuestion = [self.QuestionsByLevel objectAtIndex:j];
// ... snip ...
if (level != GameLevel) //Always happening in your current code
[QuestionsByLevel removeObjectAtIndex:j];
}
让我们看看在这段代码的几次迭代之后会发生什么。
第一次迭代:
j == 0
self.QuestionsByLevel == [Q1, Q2, Q3, Q4, Q5]
SelectedQuestion = QuestionsByLevel[0] // Q1
// The following happens because you call removeObjectAtIndex:0
QuestionsByLevel = [Q2, Q3, Q4, Q5]
第二次迭代:
j == 1
self.QuestionsByLevel == [Q2, Q3, Q4, Q5]
SelectedQuestion = QuestionsByLevel[1] // Q3
// The following happens because you call removeObjectAtIndex:1
QuestionsByLevel = [Q2, Q4, Q5]
第三次迭代:
j == 2
self.QuestionsByLevel == [Q2, Q4, Q5]
SelectedQuestion = QuestionsByLevel[2] // Q5
// The following happens because you call removeObjectAtIndex:2
QuestionsByLevel = [Q2, Q4]
第四次迭代:
j == 3
self.QuestionsByLevel == [Q2, Q4]
SelectedQuestion = QuestionsByLevel[3] // CRASH!!!!
你能看到问题吗?你的for循环假设你将通过它们的索引访问对象,但是在每次迭代之后,你将删除数组之外的东西,这会在该点之后移动所有索引。你不应该调用removeObjectAtIndex:
,因为你试图同时遍历数组。
如果您只是想跳过某个特定对象,则可以在到达该对象时调用“continue”。如果您真的想要将其从数组中删除,请致电[QuestionsByLevel removeObject:GameLevel]
。或者对你的情况有意义的事情。但是在之前迭代遍历数组。
答案 1 :(得分:9)
这不是答案。这是对你的代码的批评。
GameLevel
,Components
和level
,但从不发布任何内容。GameLevel
根本不需要alloc / init'd。您可以从[settings objectForKey:kLevelKey];
中提取值,将其分配到GameLevel
字符串中,然后使用它。然后你甚至不必释放它。self.QDetailsByLevel
属性设置为新值。你确定那是你想要的吗?if (level != GameLevel)
没有按照您的想法行事。那是比较指针(即内存中两个对象的ADDRESSES)。在当前状态下,level
和GameLevel
都已分配/初始化,这意味着它们永远不会成为同一个对象。你可能想要if ([level isEqualToString:GameLevel] == NO)
代替。[self.QuestionsByLevel count]
中减去一个以获得QuestionCount
int,这似乎是for()循环的上限。然而,for循环的条件(@Michael显示你的问题)从QuestionCount
中减去另一个 1,这意味着你的for()循环永远不会到达最后一个元素阵列。你确定那是你想要的吗?答案 2 :(得分:3)
如果我没有弄错的话,问题就出现了,因为你在迭代它的内容时正在修改对象。从列表中删除对象时,终止条件将变为无效。尝试将其作为while循环实现,并且每当从列表中删除元素时都要小心更新终止条件。您还可以使用调试器找出您的界限。