• iOS开发实用技巧—Objective-C中的各种遍历(迭代)方式


    iOS开发实用技巧—Objective-C中的各种遍历(迭代)方式

      说明:

      1)该文简短介绍在iOS开发中遍历字典、数组和集合的几种常见方式。

      2)该文对应的代码可以在下面的地址获得:https://github.com/HanGangAndHanMeimei/Code

    一、使用for循环

      要遍历字典、数组或者是集合,for循环是最简单也用的比较多的方法,示例如下: 

     1 //普通的for循环遍历
     2 -(void)iteratorWithFor
     3 {
     4     //////////处理数组//////////
     5     NSArray *arrayM = @[@"1",@"2",@"3",@"4"];
     6     NSInteger arrayMCount = [arrayM count];
     7     for (int i = 0; i<arrayMCount; i++) {
     8         NSString *obj = arrayM[i];
     9         NSLog(@"%@",obj);
    10     }
    11 
    12     //////////处理字典//////////
    13     NSDictionary *dictM = @{@"1":@"one",@"2":@"two",@"3":@"three"};
    14     NSArray *dictKeysArray = [dictM allKeys];
    15     for (int i = 0; i<dictKeysArray.count; i++) {
    16         NSString *key = dictKeysArray[i];
    17         NSString *obj = [dictM objectForKey:key];
    18         NSLog(@"%@:%@",key,obj);
    19     }
    20 
    21     //////////处理集合//////////
    22     NSSet * setM = [[NSSet alloc] initWithObjects:@"one",@"two",@"three",@"four", nil];
    23     NSArray *setObjArray = [setM allObjects];
    24     for (int i = 0; i<setObjArray.count; i++) {
    25         NSString *obj = setObjArray[i];
    26         NSLog(@"%@",obj);
    27     }
    28 
    29     //////////反向遍历----降序遍历----以数组为例
    30     NSArray *arrayM2 = @[@"1",@"2",@"3",@"4"];
    31     NSInteger arrayMCount2 = [arrayM2 count] - 1;
    32 
    33     for (NSInteger i = arrayMCount2; i>0; i--) {
    34         NSString *obj = arrayM2[i];
    35         NSLog(@"%@",obj);
    36     }
    37 }

    优点:简单

    缺点:由于字典和集合内部是无序的,导致我们在遍历字典和集合的时候需要借助一个新的『数组』作为中介来处理,多出了一部分开销。

    二、使用NSEnumerator遍历

    NSEnumerator的使用和基本的for循环类似,不过代码量要大一些。示例如下:

     1 //使用NSEnumerator遍历
     2 -(void)iteratorWithEnumerator
     3 {
     4     //////////处理数组//////////
     5     NSArray *arrayM = @[@"1",@"2",@"3",@"4"];
     6     NSEnumerator *arrayEnumerator = [arrayM objectEnumerator];
     7     NSString *obj;
     8     while ((obj = [arrayEnumerator nextObject]) != nil) {
     9         NSLog(@"%@",obj);
    10     }
    11 
    12     //////////处理字典//////////
    13     NSDictionary *dictM = @{@"1":@"one",@"2":@"two",@"3":@"three"};
    14     NSEnumerator *dictEnumerator = [dictM keyEnumerator];
    15     NSString *key;
    16     while ((key = [dictEnumerator nextObject]) != nil) {
    17         NSString *obj = dictM[key];
    18         NSLog(@"%@",obj);
    19     }
    20 
    21 
    22     //////////处理集合//////////
    23     NSSet * setM = [[NSSet alloc] initWithObjects:@"one",@"two",@"three",@"four", nil];
    24     NSEnumerator *setEnumerator = [setM objectEnumerator];
    25     NSString *setObj;
    26     while ((setObj = [setEnumerator nextObject]) != nil) {
    27         NSLog(@"%@",setObj);
    28     }
    29 
    30 
    31     //////////反向遍历----降序遍历----以数组为例
    32     NSArray *arrayM2 = @[@"1",@"2",@"3",@"4"];
    33     NSEnumerator *arrayEnumerator2 = [arrayM2 reverseObjectEnumerator];
    34     NSString *obj2;
    35     while ((obj2 = [arrayEnumerator2 nextObject]) != nil) {
    36         NSLog(@"%@",obj2);
    37     }
    38 
    39 }

    优点:对于不同的数据类型,遍历的语法相似;内部可以简单的通过reverseObjectEnumerator设置进行反向遍历。

    缺点:代码量稍大。

    三、使用for...In遍历

    在Objective-C 2.0 中增加了for ...In 形式的快速遍历。此种遍历方式语法简洁,速度飞快。示例如下:

     1 //使用for...In进行快速遍历
     2 -(void)iteratorWithForIn
     3 {
     4     //////////处理数组//////////
     5     NSArray *arrayM = @[@"1",@"2",@"3",@"4"];
     6     for (id obj in arrayM) {
     7         NSLog(@"%@",obj);
     8     }
     9 
    10     //////////处理字典//////////
    11     NSDictionary *dictM = @{@"1":@"one",@"2":@"two",@"3":@"three"};
    12     for (id obj in dictM) {
    13         NSLog(@"%@",dictM[obj]);
    14     }
    15 
    16     //////////处理集合//////////
    17     NSSet * setM = [[NSSet alloc] initWithObjects:@"one",@"two",@"three",@"four", nil];
    18     for (id obj in setM) {
    19         NSLog(@"%@",obj);
    20     }
    21 
    22     //////////反向遍历----降序遍历----以数组为例
    23     NSArray *arrayM2 = @[@"1",@"2",@"3",@"4"];
    24     for (id obj in [arrayM2 reverseObjectEnumerator]) {
    25         NSLog(@"%@",obj);
    26     }
    27 }

    优点:1)语法简洁;2)效率最高;

    缺点:无法获得当前遍历操作所针对的下标。

    四、基于Block的遍历方式

    基于Block的方式来进行遍历是最新引入的方法。它提供了遍历数组|字典等类型数据的最佳实践。示例如下:

     1 //基于块(block)的遍历方式
     2 -(void)iteratorWithBlock
     3 {
     4     //////////处理数组//////////
     5     NSArray *arrayM = @[@"1",@"2",@"3",@"4"];
     6     [arrayM enumerateObjectsUsingBlock:^(id  _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
     7         NSLog(@"%zd--%@",idx,obj);
     8     }];
     9 
    10     //////////处理字典//////////
    11     NSDictionary *dictM = @{@"1":@"one",@"2":@"two",@"3":@"three"};
    12     [dictM enumerateKeysAndObjectsUsingBlock:^(id  _Nonnull key, id  _Nonnull obj, BOOL * _Nonnull stop) {
    13         NSLog(@"%@:%@",key,obj);
    14     }];
    15 
    16     //////////处理集合//////////
    17     NSSet * setM = [[NSSet alloc] initWithObjects:@"one",@"two",@"three",@"four", nil];
    18     [setM enumerateObjectsUsingBlock:^(id  _Nonnull obj, BOOL * _Nonnull stop) {
    19         NSLog(@"%@",obj);
    20     }];
    21 
    22     //////////反向遍历----降序遍历----以数组为例
    23     NSArray *arrayM2 = @[@"1",@"2",@"3",@"4"];
    24     [arrayM2 enumerateObjectsWithOptions:NSEnumerationReverse usingBlock:^(id  _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
    25         NSLog(@"%zd--%@",idx,obj);
    26     }];
    27 }

    优点:1)遍历时可以直接从block中获得需要的所有信息,包括下标、值等。特别相对于字典而言,不需要做多余的编码即可同时获得key和value的值。

       2)能够直接修改block中key或者obj的类型为真实类型,可以省去类型转换的工作。

       3)可以通过NSEnumerationConcurrent枚举值开启并发迭代功能。

    说明:基于Block的遍历方式在实现反向遍历的时候也非常简单,使用enumerateObjectsWithOptions方法,传递NSEnumerationReverse作为参数即可,在处理遍历操作的时候推荐基于Block的遍历方式。

    五、使GCD中的dispatch_apply函数

      使用GCD中的dispatch_apply函数也能实现字典、数组等的遍历,该函数比较适合处理耗时较长、迭代次数较多的情况。示例如下:

     1 //使用GCD中的dispatch_apply函数
     2 -(void)iteratorWithApply
     3 {
     4     //////////处理数组//////////
     5     NSArray *arrayM = @[@"1",@"2",@"3",@"4"];
     6 
     7     //获得全局并发队列
     8     dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
     9 
    10     dispatch_apply(arrayM.count, queue, ^(size_t index) {
    11         NSLog(@"%@--%@",arrayM[index],[NSThread currentThread]);
    12     });
    13 }

    优点:开启多条线程并发处理遍历任务,执行效率高。

    缺点:1)对于字典和集合的处理需借助数组;2)无法实现反向遍历。

  • 相关阅读:
    Codeforces 1098C Construct a tree
    使用node查询数据库 (mysql) 时间类型字段返回日期格式不对的解决方式 何苦
    vue2中如何使用组合式API和vueuse工具包
    useSlotsTS
    arcodesignprovite项目配置参考
    Flutter配置环境
    Android项目mvvm的尝试
    华为云平台修改/etc/resolv.conf中的域
    Python将函数动态绑定为对象的成员方法
    canal学习之数据同步(一)
  • 原文地址:https://www.cnblogs.com/wendingding/p/5251937.html
Copyright © 2020-2023  润新知