NSMutableArray の中身を for ループの中で削除する方法です。

(iOS 5 で試してます。)

NSMutableArray をループを使っていらないものを削除するときに、そのままやろうとすると駄目パターンになってしまうのです。

駄目パターン1 — 実行時にエラーで落ちる

    NSMutableArray *array = [NSMutableArrayarrayWithObjects:@”A”,@”B”,@”C”, nil];

    for (NSObject *o in array) {

        [array removeObject: o];
}

fast enumerationの内部で削除しようとすると、Collection <__NSArrayM: 0x6a567e0> was mutated while being enumerated.というエラーで落ちる

 

駄目パターン2 — Arrayの途中で処理が終わってしまう

    NSMutableArray *array = [NSMutableArrayarrayWithObjects:@”A”,@”B”,@”C”, nil];

    for (int i=0; i<[array count]; i++) {

        [array removeObject:[array objectAtIndex:i]];

        NSLog(@”i: %d”, i);

    }

この場合、文字列C の前にループが終わってしまいます。
解決するにはこんな感じです。サンプルコードを2つほど。

 

解決1

    NSMutableArray *origin = [NSMutableArrayarrayWithObjects:@”A”,@”B”,@”C”, nil];

    NSMutableArray *temp = [[NSMutableArrayalloc] init];

    for (NSString *s in origin) {

        if ([s isEqual:@”B”]) {

            [temp addObject:s];

        }

    }

    [origin removeObjectsInArray:temp];

    NSLog(@”%@”, origin);

 

解決2 (ポインタごと入れ替えが可能な場合)

    NSMutableArray *origin = [NSMutableArrayarrayWithObjects:@”A”,@”B”,@”C”, nil];

    NSMutableArray *temp = [[NSMutableArrayalloc] init];

    for (NSString *s in origin) {

        if (![s isEqual:@”B”]) {

            [temp addObject:s];

        }

    }

    origin = temp;

    NSLog(@”%@”, origin);