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

エラーメッセージにあるように、foreachbucleで使用されている配列を変更することはできません。コードを次のように変更します。

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

列挙中は、配列内の要素を置き換えたり、削除したり、挿入したりすることはできません。idxnただし、要素のすべての属性をの属性に変更することはできますresult。このようにして、オブジェクトは残ります。

お役に立てれば!

于 2012-12-18T20:14:50.127 に答える