iOSの知識(2016.07)-NSMutableArrayから削除したオブジェクトの数

5164 ワード

個人のGithubのブログ、関心を求めます

1 removeObjectAtIndexとremoveObjectの違い

removeObjectAtIndex:
Removes the object at index . To fill the gap, all elements beyond index are moved by subtracting 1 from their index.
Important:Important Raises an exception NSRangeException if index is beyond the end of the array.
NSMutableArrayでindexを指定したオブジェクトを削除します.indexは境界を越えられないことに注意してください.removeObject:
Removes all occurrences in the array of a given object. This method uses indexOfObject: to locate matches and then removes them by using removeObjectAtIndex:. Thus, matches are determined on the basis of an object’s response to the isEqual: message. If the array does not contain anObject, the method has no effect (although it does incur the overhead of searching the contents).
NSMutableArrayのすべてのisEqualを削除する:削除対象オブジェクト
APIドキュメントから分かるように、両者の主な違いは、removeObjectAtIndex:が最大1つのオブジェクトしか削除できないことであり、removeObject:が複数のオブジェクトを削除できることである(isEqual:に該当するものはすべて削除される).

2 NSMutableArrayループでオブジェクトを削除する


2.1複数削除可能なアプローチ


配列の最初の@"remove"を削除
- (void)removeObjectsUseFor
{   
    NSMutableArray *contents = [@[@"how", @"to", @"remove", @"remove", @"object"] mutableCopy];
    for (NSInteger i = 0; i != contents.count; ++i) {
        NSString *var = contents[i];
        if ([var isEqualToString:@"remove"]) {
            [contents removeObject:var];
            break;
        }
    }
    
    NSLog(@"%@", contents);
}

結果は次のとおりです.
2016-07-31 21:14:13.541 RemoveObject[5862:310398] (
    how,
    to,
    object
)
removeObject:の説明から分かるように、removeObject:は、そのオブジェクト自体を削除するだけでなく、NSMutableArray内のisEqual:すべての削除対象オブジェクトのオブジェクトを削除する

2.2削除の可能性のあるアプローチ


配列内のすべての@"remove"を削除
- (void)removeObjectsUseFor
{   
    NSMutableArray *contents = [@[@"how", @"to", @"remove", @"remove", @"object"] mutableCopy];
    for (NSInteger i = 0; i != contents.count; ++i) {
        NSString *var = contents[i];
        if ([var isEqualToString:@"remove"]) {
            [contents removeObjectAtIndex:i];
        }
    }
    
    NSLog(@"%@", contents);
}

出力:
2016-07-31 21:19:59.615 RemoveObject[5886:315162] (
    how,
    to,
    remove,
    object
)

2.3崩壊を引き起こすやり方


配列内のすべての@"remove"を削除
- (void)removeObjectsUseForIn
{
    NSMutableArray *contents = [@[@"how", @"to", @"remove", @"object"] mutableCopy];
    for (NSString *var in contents) {
        if ([var isEqualToString:@"remove"]) {
            [contents removeObject:var];
        }
    }
    
    NSLog(@"%@", contents);
}

出力:クラッシュ
2016-07-31 21:27:40.337 RemoveObject[5915:321407] *** Terminating app due to uncaught exception 'NSGenericException', reason: '*** Collection <__nsarraym:> was mutated while being enumerated.'

for inループで配列内部オブジェクトを削除しないでください.

2.4正しいが違和感のあるやり方


配列内のすべての@"remove"を削除
- (void)removeObjectsReversed
{
    NSMutableArray *contents = [@[@"how", @"to", @"remove", @"remove", @"object"] mutableCopy];
    for (NSInteger i = contents.count - 1; i >= 0; --i) {
        NSString *var = contents[i];
        if ([var isEqualToString:@"remove"]) {
            [contents removeObjectAtIndex:i];
        }
    }
    
    NSLog(@"%@", contents);
}

出力:
2016-07-31 21:31:37.655 RemoveObject[5934:325316] (
    how,
    to,
    object
)

逆順序で削除して、正しいですが、少し違和感があります!

2.5優雅なやり方

- (void)removeObjectsUseEnumration
{
    NSMutableArray *contents = [@[@"how", @"remove", @"to", @"remove", @"object"] mutableCopy];
    NSIndexSet *indexSet =
        [contents indexesOfObjectsPassingTest:^BOOL(NSString *  _Nonnull var, NSUInteger idx, BOOL * _Nonnull stop) {
            return [var isEqualToString:@"remove"];
        }];
    [contents removeObjectsAtIndexes:indexSet];
    
    NSLog(@"%@", indexSet);
    NSLog(@"%@", contents);
}

出力:
2016-07-31 22:10:42.404 RemoveObject[6014:338210] [number of indexes: 2 (in 2 ranges), indexes: (1 3)]
2016-07-31 22:10:42.404 RemoveObject[6014:338210] (
    how,
    to,
    object
)

まずindexesOfObjectsPassingTest:で削除対象のindexを探し出し、removeObjectsAtIndexes:を呼び出して一度に削除します.

3まとめ

  • NSMutableArrayループでは、2.1に示すように、removeObject:を使用してNSMutableArray内部オブジェクトを削除することは推奨されません.
  • NSMutableArrayのfor inループでオブジェクトを削除することは推奨されず、2.3に示すようにクラッシュを引き起こす可能性があります.
  • NSMutableArray内部オブジェクトの削除を推奨する場合は、削除対象オブジェクトのindexを取得してから、2.5に示すように一度に削除します.