• enumerateKeysAndObjectsUsingBlock 的用法


    block是一个有序列的指令代码块,通常在代码中间花括号括起来的objective-c代码,但是它能被传递和被分配局部变量,然后作为一个参数来传递,基本上可以把花括号中间的代码保存到数据结构里。看起来就像这样子:

    NSDictionary *aDictionary = [[NSDictionary alloc] initWithObjectsAndKeys:@"zhc",@"name", nil];

        [aDictionary enumerateKeysAndObjectsUsingBlock:^(id key, id value, BOOL *stop) {

            NSLog(@"value for key %@ is %@", key, value);

            if ([@"ENOUGH" isEqualToString: key]) {

                *stop = YES;

            }

        }];

    NSDictionary有一个方法叫enumerateKeysAndObjectsUsingBlock,它就一个参数就是block,这个block携带了三个参数,这将要把dictionary里面的key和value每次一组传递到block,enumerateKeysAndObjectsUsingBlock会遍历dictionary并把里面所有的key和value一组一组的展示给你,每组都会执行这个block。这其实就是传递一个block到另一个方法,在这个例子里它会带着特定参数被反复调用,直到找到一个ENOUGH的key,然后就会通过重新赋值那个BOOL *stop来停止运行,停止遍历同时停止调用block

    ^表示这是一个block。在enumerateKeysAndObjectsUsingBlock之前定义一个局部变量,可以在block里使用,但它们都是只读的。

        BOOL stoppedEarly = NO;

        double stopValue = 53.5;

        [aDictionary enumerateKeysAndObjectsUsingBlock:^(id key, id value, BOOL *stop) {

            NSLog(@"value for key %@ is %@", key, value);

            if ([@"ENOUGH" isEqualToString:key] || ([value doubleValue] == stopValue)) {

                *stop = YES;

                stoppedEarly = YES; // ILLEGAL 违法的提示报错

            }

        }];

    不过如果你在前面加上_block,就会变成可读写了,然后在block执行完后它会保留被赋的值。

        __block BOOL stoppedEarly = NO;

        double stopValue = 53.5;

        [aDictionary enumerateKeysAndObjectsUsingBlock:^(id key, id value, BOOL *stop) {

            NSLog(@"value for key %@ is %@", key, value);

            if ([@"ENOUGH" isEqualToString:key] || ([value doubleValue] == stopValue)) {

                *stop = YES;

                stoppedEarly = YES; // 可以编译通过

            }

        }];

    在block里面用了一个实例变量,出来后也是有效的,而且不是只读的。

    typedef 一个 block:  

       typedef double (^unary_operation_t)(double op);

    这行代码的意思就是定义一个新类型,它本质上是一个block,它接受一个类型为double的参数,返回值的类型也是double的,新类型的名字叫unary_operation_t。

    已经定义好了这个类型,现在用它声明一个变量,变量名叫square,接下来给它赋值:

        unary_operation_t square;

        square = ^(double operand) {

            return operand * operand;

        }

     

    现在有了一个类型为 unary_operation_t 的变量square,怎么用呢?就像用一个C语言函数一样:

     double squareOfFive = square(5.0);

     

    把5.0作为参数传给block,5.0就是block里面的操作数,它进行平方操作,得到25。

    这有一行代码可以不用typedef直接声明square:

    double (^square)(double op) = ^(double op) { return op * op; };

    此处的square是一个变量,而不是一个类型。
    一旦定义好unary_operation_t,这种类型实际上是一个block,就可以用它进行函数声明了,把它作为函数的参数,就是声明一个参数为unary_operation_t类型的方法,比如addUnaryOperation:whichExecutesBlock:,第二个参数是block,可以用unary_operation_t来声明这个方法。首先,加入一个property:

    @property (nonatomic, strong) NSMutableDictionary *unaryOperations;

     

    它就是一个用来存储所有unaryOperations 的 dictionary,用来记录key值的dictionary

    然后实现 addUnaryOperation:whichExecutesBlock:

    typedef double (^unary_operation_t)(double op);

     

    - (void)addUnaryOperation:(NSString *)op whichExecutesBlock:(unary_operation_t)opBlock {

        [self.unaryOperations setObject:opBlock forKey:op];

    }

     

    这个方法的第二个参数是一个block,unary_operation_t指明了block的类型。把block看成一个对象,通过给定的key加入到dictionary里。block用起来像类一样,实际不是,只是有些相似,不能给它传递消息,可以像安置id一样安置它们。

     

    ARC负责block的内存管理,由于它本身并不是一个对象,它靠ARC进行内存管理,当block执行完之后,它的内存是自动释放的。

    然后我们就有了一个字典,字典的key是代表操作的字符串,值是block。接着可以这么做:

    - (double)performOperation:(NSString *)operation{

        unary_operation_t unaryOp = [self.unaryOperations objectForKey:operation];

        if (unaryOp) {

            self.operand = unaryOp(self.operand);

        }

    }

     

    大多数不用typedef来声明一个方法,比如

    - (void)enumerateKeysAndObjectsUsingBlock:(void (^)(id key, id obj, BOOL *stop))block;

    没有返回值所以是void,注意(^),在括号中间没有其他东西,是因为没有定义type。后面就是block需要的参数,然后就是block。

    block 很常见,实际上有简便方法,然后有两件事情需要去做:第一,不必去声明那些能被block里面引用的返回的type,如果它能够在block里被推断出来,比如

        NSNumber *secret = [NSNumber numberWithDouble:42.0];

        [brain addUnaryOperation:@"MoLtUaE" whichExecutesBlock:^(double operand) {

            return operand * [secret doubleValue];

        ];

     

    另外一个就是如果一个block没有参数的话,不必写这个(),比如

     [UIView animateWithDuration:5.0 animations:^{ view.opacity = 0.5;}];

     没有参数,没有返回值,仅仅是花括号。

  • 相关阅读:
    jdk环境变量配置
    Oracle常用操作命令
    Oracle数据库突然宕机,处理方案
    Oracle重启操作步骤
    大家好,我是一名程序员,这就是2017年的我……
    Oracle恢复删除数据
    网络爬虫
    第一篇博客
    函数(二)
    MFC(二)
  • 原文地址:https://www.cnblogs.com/jiuyi/p/10953691.html
Copyright © 2020-2023  润新知