在iOS中,數組是沒法經過迭代器刪除的,不管是enumerateObjectsUsingBlock迭代器仍是for in,抑或是NSEnumerator都無能爲力,固然 for循環更不行了,對於java編程的同窗來講沒法接受啊。java
固然辦法仍是有的是,否則我不會在這裏費口舌。編程
咱們主要有兩種方式來刪除數組,NSPredicate與while循環,可是性能稍有不一樣。固然這裏也會自定義迭代器刪除,也是一種不錯的選擇。數組
1.1 NSArray所有刪除性能
NSArray * aArr = @[@1,@"A",@2.0f,@"B",@"3",@4,@5,@"6"]; aArr = [aArr filteredArrayUsingPredicate:[NSPredicate predicateWithValue:NO]];
1.2 NSArray選擇性刪除ui
NSArray * aArr = @[@1,@"A",@2.0f,@"B",@"3",@4,@5,@"6"]; aArr = [aArr filteredArrayUsingPredicate:[NSPredicate predicateWithBlock:^BOOL(id _Nonnull evaluatedObject, NSDictionary<NSString *,id> * _Nullable bindings) { if([evaluatedObject isKindOfClass:[NSString class]]) { return NO; } return YES; }]];
注意:以上是NSArray的刪除方式,注意,他並非直接刪除NSArray的元素,而是刪除的是拷貝後的數組,所以,這種刪除咱們必須經過接收返回值來獲得新的數組集合atom
若是是NSMutableArray,咱們可使用新增的方法,這種方式是直接刪除,可是原理和NSArray一致,都是從內部將新的集合複製給素組lua
1.3 NSMutableArrayspa
NSArray * aArr = @[@1,@"A",@2.0f,@"B",@"3",@4,@5,@"6"]; NSMutableArray * bArr = [NSMutableArray arrayWithArray:aArr]; [bArr filterUsingPredicate:[NSPredicate predicateWithBlock:^BOOL(id _Nonnull evaluatedObject, NSDictionary<NSString *,id> * _Nullable bindings) { NSLog(@"count=%ld",[bArr indexOfObject:evaluatedObject]); if([evaluatedObject isKindOfClass:[NSString class]]) { return NO; } return YES; }]];
關於NSPredicate刪除數組是一種能夠選擇的方法,咱們從Block中打印 count發現,原數組元素基本不會改變,所以咱們推測,NSPredicate過濾運行流程以下:code
①NSPredicate是複製原數組,複製到一個新的集合,假定稱爲集合CopyAorm
②經過Block過濾器過濾出集合CopyA中的元素元素到另外一個數組集合,假定這個集合爲集合CopyB
③返回過濾數組集合CopyB,釋放集合CopyA,完成賦值到初始集合
在整個過程當中,出現了過多的數組元素引用和數組賦值,形成使用內存過大,若是NSArray存儲的是小數據,而不是多媒體或者大文本,能夠不用忌諱。可是若是涉及到大圖片,咱們這種刪除顯然是有代價的,也就是可能出現OOM問題。
對於while循環,他的做用對象只能是NSMutableArray,所以,對於NSArray咱們須要適當的轉換成NSMutableArray。
2.1選擇性清除方案(迭代刪除)
NSArray * aArr = @[@1,@"A",@2.0f,@"B",@"3",@4,@5,@"6"]; //數組轉換 NSMutableArray * bArr = [NSMutableArray arrayWithArray:aArr]; aArr = [aArr filteredArrayUsingPredicate:[NSPredicate predicateWithValue:NO]]; //釋放元素內存 aArr = nil; int i = 0; while(bArr.count>i) { NSObject * itemObject = [bArr objectAtIndex:i]; if([itemObject isKindOfClass:[NSString class]]) { [bArr removeObject:itemObject]; //釋放 itemObject = nil; }else{ i++; } } aArr = bArr;
這種方式效率顯而易見,不只消耗內存少,並且效率相對較高,固然咱們選擇逆序迭代的時候結果也是同樣。
NSArray * aArr = @[@1,@"A",@2.0f,@"B",@"3",@4,@5,@"6"]; //數組轉換 NSMutableArray * bArr = [NSMutableArray arrayWithArray:aArr]; aArr = [aArr filteredArrayUsingPredicate:[NSPredicate predicateWithValue:NO]]; //釋放元素內存 aArr = nil; int i = 0; while(bArr.count>i) { NSObject * lastObject = [bArr lastObject]; if([itemObject isKindOfClass:[NSString class]]) { [bArr removeLastObject]; //釋放 itemObject = nil; }else{ i++; } } aArr = bArr;
特別的,對於迭代所有刪除,如NSArray<UIImage * > * 數組中的圖片壓縮存儲,爲了及時釋放內存,這種優點會體現的更加明顯
NSArray * aArr = @[@1,@"A",@2.0f,@"B",@"3",@4,@5,@"6"]; //數組轉換 NSMutableArray * bArr = [NSMutableArray arrayWithArray:aArr]; aArr = [aArr filteredArrayUsingPredicate:[NSPredicate predicateWithValue:NO]]; //釋放元素內存 aArr = nil; while(bArr.count>0) { NSObject * lastObject = [bArr lastObject]; // 壓縮,存儲你的圖片 [bArr removeLastObject]; //釋放就圖片 }
NSArray 自帶迭代器,但刪除操做會引發Crash,所以咱們須要自定義本身的迭代器,實現可刪除迭代器
Iterator.h文件 |
#import <Foundation/Foundation.h> @protocol Iterator <NSObject> @required /** * 判斷數組是否還有元素 */ -(BOOL) hasNext; /** * 返回數組中的元素(索引爲0的元素),必須先使用hasNext判斷,不然可能出現數組越界異常 */ -(NSObject *) next; /** * 刪除數組中的元素(索引爲0的元素),必須先使用hasNext判斷,不然可能出現數組越界異常 */ -(void) remove; @end
NSMutableArray+Helper.h類目文件 |
#import <Foundation/Foundation.h> #import "Iterator.h" @interface NSMutableArray(Helper) /** * * 返回一個迭代器 */ -(id<Iterator> ) iterator; @end
NSMutableArray+Helper.m類目文件 |
#import "NSMutableArray+Helper.h" /** * *實現私有類實現 */ @interface NSMutableArrayIterator:NSObject<Iterator> /** *自定義初始化方法 * @param array 目標數組,NSMutableArray 類型 */ -(instancetype) initWidthMutableArray:(NSMutableArray *) array; /** * 持有的目標數組 */ @property (nonatomic,strong) NSMutableArray * array; @property (nonatomic,assign) int nextIndex; @property (nonatomic,assign) int currentIndex; @end @implementation NSMutableArrayIterator -(instancetype) initWidthMutableArray:(NSMutableArray *) array { if(self=[super init]) { _array = array; _nextIndex = 0; _currentIndex = 0; } return self; } -(BOOL) hasNext { return _array!=nil && _array.count>_currentIndex; } -(NSObject *) next { _nextIndex ++ ; _currentIndex = _nextIndex - 1; if(_currentIndex>(_array.count-1)) { NSException *e = [NSException exceptionWithName: @"索引越界" reason: @"迭代索引錯誤,不能大於元素數量" userInfo: nil]; @throw e; } return [_array objectAtIndex:(_currentIndex)]; } -(void) remove { if(_currentIndex<0) { NSException *e = [NSException exceptionWithName: @"狀態異常" reason: @"迭代索引錯誤,不能小於0" userInfo: nil]; @throw e; } [_array removeObjectAtIndex:(_currentIndex)]; if (_currentIndex< _nextIndex ) { _nextIndex--; _nextIndex = _nextIndex>0?_nextIndex:0; } _currentIndex= -1; } @end @implementation NSMutableArray(Helper) -(id<Iterator>) iterator{ NSMutableArrayIterator * iteratorArray = [[NSMutableArrayIterator alloc] initWidthMutableArray:self]; return iteratorArray; } @end
到這一步,咱們完成了整個實現,所以,對於NSArray數組刪除,咱們須要將其轉爲NSMutableArray進行刪除
這裏使用 Windows版本的LLVM+GNUstep編譯運行Objective-C代碼