美文网首页网络请求ios A知识点
iOS随笔——初识枚举器enumerateObjectsUsin

iOS随笔——初识枚举器enumerateObjectsUsin

作者: bluedaquiri | 来源:发表于2016-12-02 17:56 被阅读8333次
    枚举器是一种苹果官方推荐的更加面向对象的一种遍历方式,相比于for循环,它具有高度解耦、面向对象、使用方便等优势

    1.测试场景

    一个未知内部数据的数组,判断数组中是否有字符串@"2"
    方式:通过遍历,判断数组元素是否等于@"2"

    [@[@"1",@"2",@"3"] enumerateObjectsUsingBlock:^(id  _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
            if ([obj isEqualToString:@"2"]) {
                NSLog(@"smart string is at index %lu",(unsigned long)idx);
                *stop = YES;
            }
        }];
    

    打印信息:smart string is at index 1

    2.实现原理

    你是否思考过它的内部实现方式?
    那么让我们来重写一个它的内部实现,通过NSArray的分类给外界提供一个测试方法,来模拟它的内部实现(不开源,只能猜测 0^0)

    - (void)enumTestBlock:(void (^)(id, NSUInteger, BOOL *))enumBlock {
        if (!enumBlock && self.count == 0) return;
        BOOL stop = NO;
        for (int index = 0; index < self.count; index++ ) {
            if (!stop) {
                enumBlock(self[index], index, &stop);
            } else {
                break;
            }
        }
    }
    

    外部调用:

     [@[@"1",@"2",@"3"] enumTestBlock:^(id obj, NSUInteger idx, BOOL *stop) {
            if ([obj isEqualToString:@"2"]) {
                NSLog(@"smart test string is at index %lu",(unsigned long)idx);
                *stop = YES;
            }
        }];
    

    打印信息:smart test string is at index 1


    这里唯一需要注意就是Block内传入的一个bool类型的指针参数BOOL *stop,是为了外部能在同一内存地址上修改内部实现中的变量stop的值,来实现跳出循环的功能


    3.自定义枚举器实战场景

    在看MJExtension源码时发现了这种有意思的自定义枚举器,用于遍历所有的类,直到遇到Foundation类时跳出循环

    typedef void (^MJClassesEnumeration)(Class c, BOOL *stop);
    + (void)mj_enumerateClasses:(MJClassesEnumeration)enumeration;
    + (void)mj_enumerateClasses:(MJClassesEnumeration)enumeration {
        // 1.没有block就直接返回
        if (enumeration == nil) return;
        // 2.停止遍历的标记
        BOOL stop = NO;
        // 3.当前正在遍历的类
        Class c = self;
        // 4.开始遍历每一个类
        while (c && !stop) {
            // 4.1.执行操作
            enumeration(c, &stop);
            // 4.2.获得父类
            c = class_getSuperclass(c);
            if ([MJFoundation isClassFromFoundation:c]) break;
        }
    }
    

    相信这样的处理方式也是苹果官方更推荐的一种方式

    相关文章

      网友评论

        本文标题:iOS随笔——初识枚举器enumerateObjectsUsin

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