0

我有一个包含对象列表的 NSMutableArray。我想要做的是遍历这个对象列表,并为我要插入的对象找到匹配的对象。一旦找到匹配的对象,我就想简单地用我要插入的对象替换当前列表中的对象。我正在尝试使用快速枚举来做到这一点:

TestResult *result = [[TestResult alloc] init];
    [result setName:name];
    [result setScore:score];
    [result setDateStamp:date];


    for (TestResult *checkTest in [DataModel sharedInstance].testResultList) {

        NSInteger indx = [[DataModel sharedInstance].testResultList indexOfObjectPassingTest:^BOOL(TestResult *obj, NSUInteger idx, BOOL *stop) {
            return [obj.name isEqualToString:name];
        }];

        if (indx != NSNotFound) {

            [[DataModel sharedInstance].testResultList replaceObjectAtIndex:indx withObject:result];

        }

    }

不幸的是,当我运行上面的代码时,我收到以下错误:

*** Terminating app due to uncaught exception 'NSGenericException', reason: '*** Collection <__NSArrayM: 0x9624820> was mutated while being enumerated.'

谁能看到我做错了什么,如何解决这个问题,同时实现我上面描述的功能?

4

4 回答 4

4

首先,崩溃是不言自明的。您实际上是在变异(也就是替换数组中的一个对象),而快速枚举仍在进行中,这是不允许的。

如果您要采用您的设计,解决方案将是实际捕获对象的索引,打破快速枚举并替换快速枚举之外的对象。

但是,您正在做的事情是不正确的。使用 indexOfObjectPassingTest 的方法是这样的:

NSInteger indx = [[DataModel sharedInstance].testResultList indexOfObjectPassingTest:^BOOL(TestResult *obj, NSUInteger idx, BOOL *stop) {
    return [obj.name isEqualToString:name];
}];

if (indx != NSNotFound) {

    [[DataModel sharedInstance].testResultList replaceObjectAtIndex:indx withObject:result];

}

您不需要手动枚举数组的所有元素。该函数在内部为您执行此操作。

于 2012-12-18T20:14:20.170 回答
0

正如错误消息所说,您无法编辑正在枚举的数组。你需要有一个不同的数组,然后你可以这样做。

以下会起作用,

TestResult *result = [[TestResult alloc] init];
[result setName:name];
[result setScore:score];
[result setDateStamp:date];

NSArray *array = [NSArray arrayWithArray:[DataModel sharedInstance].testResultList];    

for (TestResult *checkTest in array) {

    NSInteger indx = [[DataModel sharedInstance].testResultList indexOfObjectPassingTest:^BOOL(TestResult *obj, NSUInteger idx, BOOL *stop) {
        return [obj.name isEqualToString:name];
    }];

    if (indx != NSNotFound) {
        [[DataModel sharedInstance].testResultList replaceObjectAtIndex:indx withObject:result];
    }
}

更新: 根据 Lefteris 的评论,如果您使用indexOfObjectPassingTest方法,则不需要遍历数组。

你可以简单地使用,

TestResult *result = [[TestResult alloc] init];
[result setName:name];
[result setScore:score];
[result setDateStamp:date];

NSInteger indx = [[DataModel sharedInstance].testResultList indexOfObjectPassingTest:^BOOL(TestResult *obj, NSUInteger idx, BOOL *stop) {
    return [obj.name isEqualToString:name];
}];

if (indx != NSNotFound) {
    [[DataModel sharedInstance].testResultList replaceObjectAtIndex:indx withObject:result];
}
于 2012-12-18T20:08:30.560 回答
0

正如错误消息所说,您无法修改 foreach bucle 中使用的数组。将您的代码更改为:

TestResult *result = [[TestResult alloc] init];
[result setName:name];
[result setScore:score];
[result setDateStamp:date];

NSInteger indx = NSNotFound;
for (TestResult *checkTest in [DataModel sharedInstance].testResultList) {

    indx = [[DataModel sharedInstance].testResultList indexOfObjectPassingTest:^BOOL(TestResult *obj, NSUInteger idx, BOOL *stop) {
        return [obj.name isEqualToString:name];
    }];
}
if (indx != NSNotFound) {
    [[DataModel sharedInstance].testResultList replaceObjectAtIndex:indx withObject:result];                            
}
于 2012-12-18T20:09:49.120 回答
0

枚举时不能替换、删除或插入数组中的元素。但是您可以将元素的所有属性更改idxnresult. 这样对象就保留了。

希望这可以帮助!

于 2012-12-18T20:14:50.127 回答