在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代码