美文网首页
iOS NSEnumerator的用法

iOS NSEnumerator的用法

作者: 天空的羁绊 | 来源:发表于2017-11-13 14:29 被阅读165次

    1、字典中的(有两个方法):

    //获取所有key值
    -(NSEnumerator<KeyType> *)keyEnumerator;
    //获取所有value值
    -(NSEnumerator<ObjectType> *)objectEnumerator;
    

    示例:

    - (instancetype)initWithDictionary:(NSDictionary *)dic{
        if (self = [super init]) {
            NSEnumerator * enumeration = [dic keyEnumerator];
            id key, value;
            while (key = [enumeration nextObject]) {
                value = [dic valueForKey:key];
                [self setValue:value forKey:key];
            }
        }
        return self;
    }
    

    经过几次测试,发现通过keyEnumerator,和objectEnumerator返回的数组都是与字典中的key和value的一一对应的。虽然不明所以,但仍然可以这样:

    - (instancetype)initWithDictionary:(NSDictionary *)dic{
       if (self = [super init]) {
           NSEnumerator * key_enumeration = [dic keyEnumerator];
           NSEnumerator * value_enumeration = [dic objectEnumerator];
           id key, value;
           while (key = [key_enumeration nextObject]) {
               value = [value_enumeration nextObject];
               [self setValue:value forKey:key];
           }
       }
       return self;
    }
    

    二、数组中的(有两个方法)

    //正向遍历数组 ——>完全可用 for in 语法代替
    - (NSEnumerator<ObjectType> *)objectEnumerator;
    //反向遍历数组
    - (NSEnumerator<ObjectType> *)reverseObjectEnumerator;
    

    示例:

    NSArray *array= [NSArray arrayWithObjects:
                     @"112",@"234",@"3434",@"3455" ,nil];
    
    NSEnumerator *enumerator = [array reverseObjectEnumerator];
    
    id thing;
    while (thing = [enumerator nextObject]) {
        NSLog(@"Ifound %@",thing);
    }
    

    //也可以这样

    NSArray *array= [NSArray arrayWithObjects:
                     @"112",@"234",@"3434",@"3455" ,nil];
    NSEnumerator *enumerator = [array reverseObjectEnumerator];
    
    NSArray *arr = [enumerator allObjects];
    
    for (NSString *res in arr) {
        NSLog(@"%@",res);
    }
    

    注意:
    1、-(NSEnumerator *)objectEnumerator;
    返回:一个枚举器对象,可让您访问字典中的每个值。
    注意:如果您将此方法与NSDictionary的可变子类的实例一起使用,则您的代码不应在枚举过程中修改条目。 如果您打算修改条目,请使用allValues方法创建字典值的“快照”。 从这个快照中修改值。
    2、- (ObjectType)nextObject;
    枚举集合中的下一个对象,或当所有对象已经枚举完成时:为nil。
    3、@property(readonly, copy) NSArray<ObjectType> *allObjects;
    返回:未枚举对象的数组
    该数组按枚举顺序包含枚举器中所有剩余对象。
    它不包含之前已经调用nextObject消息的枚举对象。
    访问该属性会耗尽枚举器集合,这会导致随后调用nextObject会返回nil。

    .
    .
    .
    以下内容未验证

    基于块的枚举

    在iOS 4中为Cocoa Touch框架中的集合对象引入了基于块的枚举(Block-Based Enumeration)。块是Objective-C的一项语言功能(本书写作时,苹果公司还在争取把块作为对C语言的扩展而标准化)。块是一种类型化的函数,就是说块是函数也是类型。定义好的块是一个可在方法调用之间传递的变量,就跟对象中的其他变量一样。同时,块变量在方法中可作为函数使用。当把块作为参数传递给方法时,块可以像C程序中的函数指针那样被用作回调函数。因此块正适合于实现内部迭代器(枚举器)。客户端不再需要手动生成迭代器,只需要提供一个符合目标集合对象所要求的签名的块。然后块将在每个遍历步骤中被调用。在每次块被目标集合对象调用时,定义块的算法可以对返回的元素进行处理。

    块是Objective-C语言中很酷的一项功能。它让我们可以把回调算法的定义内嵌在消息调用之中。如果不使用块,在Cocoa Touch框架中实现“回调”的传统方式是使用委托(见适配器模式,第8章)。需要为要响应客户端回调的所有对象(适配器)单独定义一个协议(目标)。要是应用程序的这个部分复杂到需要另外的适配器机制的程度,那也未尝不可。有时块可以提供一种比枚举器更漂亮的解决方案。

    在iOS 4中,苹果公司在NSArray、NSDictionary和NSSet对象中引入了新方法,用于基于块的枚举。其中一个方法叫enumerateObjectsUsingBlo<wbr style="box-sizing: border-box;">ck:(void (^)(id obj, NSUInteger idx, BOOL *stop))block。我们可以把自己的算法定义在内嵌到消息调用之中的块里,或者在别的什么地方预先定义一个块,然后作为参数传给消息调用。下面的代码段通过一个NSArray对象演示了它是如何在代码中实现的。

    NSArray *anArray=[NSArray arrayWithObjects:@"This", @"is", @"a", @"test", nil]; 
    NSString *string=@"test";
    [anArray enumerateObjectsUsingBlock:^(id obj, NSUInteger index, BOOL *stop)
    {
      if([obj localizedCaseInsensitiveCompare:string] == NSOrderedSame)
      {
        // 对返回的obj做点别的事情
      *stop=YES;
    
      }
    

    要是anArray对象中有个单词是@"test",那么就把指针*stop设置为YES,以通知anArray对象提前停止枚举。块除了id obj和BOOL *stop参数,还有一个NSUInteger index参数。index参数让块中的算法知道当前元素的位置,这对这样的并发枚举非常有用。要是没有这个参数,访问索引的唯一方式就是使用indexOfObject:方法,这样影响效率。

    NSSet对象中基于块的枚举与NSArray对象中的非常类似,只是在块签名中没有index参数。NSSet对象是一种模拟“集合”(set)的数据结构,集合中的元素没有表示元素在结构中位置的索引。

    使用NSArray、NSDictionary和NSSet的内部迭代器的一个重要好处是,处理其内容的算法可在其他地方由其他开发人员来定义。与传统的for循环中定义的算法不同,定义清晰的块可被复用。当块逐渐变大时,可把它们放到单独的实现文件中,不跟其他代码挤在一起。虽然块是一种为复杂的事物添加内联算法的方便途径,无需定义单独的委托协议,但是当块过大而难以维护时,应该考虑使用策略模式(第19章)。

    <a name="t1" style="box-sizing: border-box; background: transparent; color: rgb(79, 161, 219); text-decoration: none; margin: 0px; padding: 0px; font-weight: normal; outline: none;"></a>快速枚举

    Objective-C 2.0提供了一种枚举,称为快速枚举。它是苹果公司推荐的枚举方法。它允许把对集合对象的枚举直接用作for循环的一部分,无需使用其他枚举器对象,而且比传统的基于索引的for循环效率更高。快速枚举的语法如下。

    NSArray * anArray = ... ;
    for (NSString * item in anArray)
    {
      // 对item作些处理
    }
    

    现在枚举循环使用指针运算(pointer arithmetic),让它比使用NSEnumerator的标准方法效率更高。

    要利用快速枚举,集合类需要实现NSFastEnumeration协议,以向运行库提供关于集合的必要信息。基础框架中的所有集合类与NSEnumerator类都支持快速枚举。因此不必使用while循环从NSEnumerator枚举每个元素,直到nextObject返回nil,我们可以使用其快速枚举的版本,如下面的代码段所示。

    NSArray * anArray = ... ;
    NSEnumerator * itemEnumerator = [anArray objectEnumerator];
    for (NSString * item in itemEnumerator)
    {
      // 对item作些处理 
    }
    

    虽然既可以使用集合对象的快速枚举,也可以使用枚举器的快速枚举,但如果只需要默认遍历(通常只按升序),直接对集合对象进行快速枚举更为合理。NSEnumerator使用其nextObject方法实现NSFastEnumeration协议。从性能上说,它比直接在while循环中手动调用这个方法好不了多少。尽管跟传统的使用nextObject的while循环相比,快速枚举中的for循环显得更为整洁。

    实现NSFastEnumeration不在本书的范围,所以不在此讨论它。

    <a name="t2" style="box-sizing: border-box; background: transparent; color: rgb(79, 161, 219); text-decoration: none; margin: 0px; padding: 0px; font-weight: normal; outline: none;"></a>内部枚举

    NSArray有个实例方法叫(void)makeObjectsPerformSelect<wbr style="box-sizing: border-box;">or:(SEL)aSelector,它允许客户端向数组中每个元素发送一个消息,让每个元素执行指定的aSelector(假定元素支持它)。可以用前面提到的任何一种枚举方法让每个元素执行相同的选择器,达到相同的目的。这个方法在内部枚举集合并向每个元素发送performSelector:消息。这种方式的缺点是如果集合中任何元素不响应选择器,就会抛出异常。因此它主要适用于不需太多运行时检查的简单操作。

    原文链接1: http://blog.sina.com.cn/s/blog_7cdd1b3501010076.html
    原文链接2:http://blog.csdn.net/hdfqq188816190/article/details/52754406

    相关文章

      网友评论

          本文标题:iOS NSEnumerator的用法

          本文链接:https://www.haomeiwen.com/subject/qqxzmxtx.html