需要修改在iOS中快速枚举期间预加载数据的NSMutableArray

时间:2012-12-18 20:04:18

标签: ios nsmutablearray enumeration fast-enumeration

我有一个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 个答案:

答案 0 :(得分: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];

}

您无需手动枚举数组的所有元素。 该功能在内部为您完成。

答案 1 :(得分: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];
}

答案 2 :(得分: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];                            
}

答案 3 :(得分:0)

枚举时,不能替换,删除或插入数组中的元素。但您可以将idxn处元素的所有属性更改为result的属性。这样就可以保留物体了。

希望这有帮助!