我們?cè)诒闅v可變數(shù)組時(shí),最好不要做刪除數(shù)組中元素的操作。
因?yàn)閯h除操作可能會(huì)引起數(shù)組容量的變化,導(dǎo)致數(shù)組越界等問(wèn)題。
以前在使用for循環(huán)遍歷的時(shí)候遇到過(guò)這個(gè)問(wèn)題。
當(dāng)時(shí)的做法是使用enumerateObjectsUsingBlock:,但是這次又遇到這個(gè)問(wèn)題時(shí),順便好好的測(cè)試了一下for、for in、enumerateObjectsUsingBlock:。
實(shí)驗(yàn)結(jié)果如下:
NSMutableArray*array = [NSMutableArrayarrayWithArray:@[@"1",@"2",@"3",@"4",@"5"]];[array enumerateObjectsUsingBlock:^(id_Nonnull obj, NSUInteger idx,BOOL* _Nonnull stop) {if([obj isEqualToString:@"3"]) {? ? ? ? [array removeObject:obj];? ? }}];NSLog(@"%@",array);// 輸出結(jié)果:(1,2,4,5)
1
2
3
4
5
6
7
8
9
1
2
3
4
5
6
7
8
9
結(jié)果正常。
使用for in:
NSMutableArray *array= [NSMutableArray arrayWithArray:@[@"1",@"2",@"3",@"4",@"5"]];for(NSString *objinarray) {if([obj isEqualToString:@"3"]) {? ? ? ? [arrayremoveObject:obj];? ? }}NSLog(@"%@",array);
1
2
3
4
5
6
7
1
2
3
4
5
6
7
結(jié)果出現(xiàn)崩潰,信息如下:
2016-11-1122:48:06.886Solutions[15297:2231002] *** Terminating app duetouncaughtexception'NSGenericException', reason:'*** Collection <__NSArrayM: 0x1001060b0> was mutated while being enumerated.'*** First throw call stack:(0CoreFoundation0x00007fff929c14f2__exceptionPreprocess +1781libobjc.A.dylib0x00007fff8fcb2f7eobjc_exception_throw +482CoreFoundation0x00007fff92a2815c__NSFastEnumerationMutationHandler +3003Solutions0x0000000100000d1cmain +5084libdyld.dylib0x00007fff90cd05adstart +1)libc++abi.dylib: terminatingwithuncaughtexceptionoftypeNSException
1
2
3
4
5
6
7
8
9
10
1
2
3
4
5
6
7
8
9
10
使用for:
NSMutableArray *array= [NSMutableArray arrayWithArray:@[@"1",@"2",@"3",@"4",@"5"]];for(inti =0; i
1
2
3
4
5
6
7
8
9
1
2
3
4
5
6
7
8
9
結(jié)果正常,可能是蘋果對(duì)普通的for循環(huán)內(nèi)部的處理做了修正,以前這樣寫(xiě)是會(huì)報(bào)錯(cuò)的。
其實(shí),最正確與穩(wěn)妥的方案,是對(duì)數(shù)組逆序遍歷,然后再刪除元素就沒(méi)有問(wèn)題了。
例如for in的逆序遍歷:
NSMutableArray *array= [NSMutableArray arrayWithArray:@[@"1",@"2",@"3",@"4",@"5"]];for(NSString *obj inarray.reverseObjectEnumerator) {if([obj isEqualToString:@"3"]) {? ? ? ? [arrayremoveObject:obj];? ? }}NSLog(@"%@",array);// 輸出結(jié)果:(1,2,4,5)
1
2
3
4
5
6
7
8
1
2
3
4
5
6
7
8
使用
NSMutableArray*array = [NSMutableArrayarrayWithArray:@[@"1",@"2",@"3",@"4",@"5"]];[array enumerateObjectsWithOptions:NSEnumerationReverse usingBlock:^(id_Nonnull obj, NSUInteger idx,BOOL* _Nonnull stop) {if([obj isEqualToString:@"3"]) {? ? ? ? ? ? ? ? [array removeObject:obj];? ? ? ? ? ? }? ? ? ? }];NSLog(@"%@",array);// 輸出結(jié)果:(1,2,4,5)
1
2
3
4
5
6
7
8
9
1
2
3
4
5
6
7
8
9
關(guān)于for 的逆序
NSMutableArray *array= [NSMutableArray arrayWithArray:@[@"1",@"2",@"3",@"4",@"5"]];for(inti =array.count -1; i >=0; i--) {? ? NSString *obj =array[i];if([obj isEqualToString:@"3"]) {? ? ? ? [arrayremoveObject:obj];? ? }}NSLog(@"%@",array);// 輸出結(jié)果:(1,2,4,5)
1
2
3
4
5
6
7
8
9
1
2
3
4
5
6
7
8
9
以前做Java開(kāi)發(fā)的時(shí)候,也遇到過(guò)這種遍歷刪除元素的,那時(shí)候的做法是在遍歷,刪除元素后做一次i–操作。
現(xiàn)在想來(lái),也可以逆序遍歷然后直接刪除即可。
====================================
或者樓主可以用 while 循環(huán)語(yǔ)句來(lái)做。
例如:
while(array.count>0)
{
obj = [array objectAtIndex:0];
//判斷處理
…
//remove
[array removeObjectAtIndex:0];
}
=========================================
可以用NSPredicate來(lái)完成:
NSArray *sourceArray = @[];
NSArray *whatYouNeedArray = [sourceArray filteredArrayUsingPredicate:[NSPredicate predicateWithBlock:^BOOL(id evaluatedObject, NSDictionary *bindings) {
return ![evaluatedObject shouldBeDeleted];
}]];
whatYouNeedArray就是你要的array,已經(jīng)去除掉該刪除的項(xiàng)。
=======================================
一般不要這樣做,如果要?jiǎng)h除,一定要在刪除之后,break.
Oc語(yǔ)言中有三種遍歷數(shù)組的方式,一是傳統(tǒng)的for循環(huán),二是for-in循環(huán),三是迭代器。其中,第一種方式的效率最低。第二種遍歷方法如下,第三種使用比較少,你可以自己去網(wǎng)上看下。
for (NSString * str in names)
{
if ([str isEqualTo: @"something"]){
[names removeObject: str];
break;//一定要有break,否則會(huì)出錯(cuò)的。
}
}