iOS 數組遍歷刪除&自定義迭代器

在iOS中,數組是沒法經過迭代器刪除的,不管是enumerateObjectsUsingBlock迭代器仍是for in,抑或是NSEnumerator都無能爲力,固然 for循環更不行了,對於java編程的同窗來講沒法接受啊。java

固然辦法仍是有的是,否則我不會在這裏費口舌。編程


咱們主要有兩種方式來刪除數組,NSPredicate與while循環,可是性能稍有不一樣。固然這裏也會自定義迭代器刪除,也是一種不錯的選擇數組


一.使用NSPredicate刪除數組元素

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循環遍歷刪除(推薦)

對於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代碼


相關文章
相關標籤/搜索