zoukankan      html  css  js  c++  java
  • Block 朴实理解

    转载自:http://www.cnblogs.com/lzz900201/archive/2013/04/17/3025340.html

    block是个什么玩意儿

    Block是Apple Inc.为C、C++以及Objective-C添加的特性,使得这些语言可以用类lambda表达式的语法来创建闭包 ——维基百科

    A block is an anonymous inline collection of code, and sometimes also called a "closure". ——Apple文档

    闭包就是能够读取其它函数内部变量的函数。

    这里简单总结一下用法。block的用法有很多种,最常用的有 回调 和 遍历 。这篇主要说 回调

    1. 回调

      什么是回调

      在计算机程序设计中,回调函数,或简称回调(Callback),是指通过函数参数传递到其它代码的,某一块可执行代码的引用。这一设计允许了底层代码调用在高层定义的子程序。 ——维基百科

      回调就是说,我一个操作执行完成之后,提供给调用者一个接口,供调用者定义一些操作。obj-C的代理模式就是典型的回调。

      举个简单的block例子:

       @interface People : NSObject
      
       -(void)runningOutOfMoneyUsingBlock:(void (^)(void))aBlok;
      
       @end
      
      
       @implementaiton People
      
       -(void)runningOutOfMoneyUsingBlock:(void (^)(void))aBlok
       {
           NSLog(@"I have run out of my money");
           aBlock();     //(1)
       }
      
       @end
      

      这个时候, 就定义了一个带block参数的方法。这是一个很简单的block参数, 没有返回值, 没有参数。

      当我们调用这个方法的时候,只需这样操作:

       Peopeo *aPeople = [[People alloc] init]];
       [aPeople runningOutOfMoneyUsingBlock:^{
      
           NSLog(@"Earn more money!");
      
       }];
      

      这时在执行People类方法的时候,执行结果如下:

       “I have run out of my mondy”
       "Earn more money!"
      

      很好理解,People的类方法有一个block参数。调用者在调用该方法的时候为block参数定义了若干操作(这里是输出一句话),然后将这些操作作为参数传递给类方法内部执行.调用者所定义的这些操作执行的位置,取决于"(1)"所处的位置。

      如果将类方法的实现改变为:

       -(void)runningOutOfMoneyUsingBlock:(void (^)(void))aBlok
       {
           aBlock();     //(1)
           NSLog(@"I have run out of my money");
       }
      
       @end
      

      那么运行结果就会变为:

       "Earn more money!"
       “I have run out of my money”
      

      下面来说一说block 带参数 的情况,有People类方法定义如下:

       @interface People : NSObject
      
       -(void)runningOutOfMoneyUsingBlock:(void (^)(int a, int b))aBlok;
      
       @end
      
       @implementaiton People
      
       -(void)runningOutOfMoneyUsingBlock:(void (^)(int a, int b))aBlok
       {
           NSLog(@"I have run out of my money");
           int a = 10;
           int b = 50
           aBlock(a,b);     //(2)
       }
      
       @end
      

      在这个类方法中,对之前的People类方法的block参数进行了扩展,加入了两个整形参数:a和b。在调用block之前为a和b赋值并且传给了block,形如(2)。

      这个时候,当我们在调用这个类方法的时候,就会出现这样的情况:

       Peopeo *aPeople = [[People alloc] init]];
       [aPeople runningOutOfMoneyUsingBlock:^(int a, int b){
      
           NSLog(@"a = %d, b = %d", a, b);
      
       }];
      

      执行结果如下:

       "Earn more money!"
       "a = 10, b = 50"
      

      不难看出,People将自己内部的两个局部变量, 通过block传递给了调用者。这一点很好理解,想想我们经常使用的 代理方法 就可以了。

      以UITableView的代理方法为例,代理方法定义如下

       - (void)tableView(UITableView *):tableView didSelectRowAtIndexPath:(NSIndexPath)indexPath;
      

      这个方法用来给某个section指定行数。私以为这个方法可以换为如下block实现。

       @interface UITableView (WithBlock)
      
       -(void)didSelectRowAtIndexPathUsingBlock:(void (^)(UItableView *tableView, NSIndxPath *indexPath))selectBlock;
      
       @end
      
      
       @implementation UITableView (WithBlock)
      
       -(void)didSelectRowAtIndexPathUsingBlock:(void (^)(UItableView *tableView, NSIndxPath *indexPath))selectBlock
       {
           //some other code
           ...
           if(selectBlock) {
               selectBlock(self, indexPath);
           }
      
           …
           //some other code
       }
      
       @end
      

      好吧, 我承认这里给出这样的方法有点儿蹩脚,仅仅是为了对比Block和代理的相似之处。回想一下代理的实现,block是一样的原理。

      block还可以有返回值,将block在调用者处执行的结果返回给方法本身。例如,再对以上实例方法进行扩展,代码如下:

        @interface People : NSObject
      
       -(void)runningOutOfMoneyUsingBlock:(int (^)(int a, int b))aBlok;
      
       @end
      
       @implementaiton People
      
       -(void)runningOutOfMoneyUsingBlock:(int (^)(int a, int b))aBlock
       {
           NSLog(@"I have run out of my money");
           int a = 10;
           int b = 50
           int m = 0;
           if(aBlock)
           {
               m = aBlock(a,b);     //(2)
           }
           NSLog(@"aBlock的返回值为:%d",m);
      
       }
      
       @end
      

      调用该方法:

       [aPeople runningOutOfMoneyUsingBlock^(int a, int b){
           return a + b;
       }];
      

      执行结果为:

       "I have run out of money"
       "aBlock的返回值为:60"
  • 相关阅读:
    android 本地字符串存取
    2020-07-17:线上一个服务有4个实例突然变得访问很慢,你会从什么地方入手找原因?
    2020-07-16:如何获得一个链表的倒数第n个元素?
    2020-07-15:死锁与活锁的区别,死锁与饥饿的区别?
    2020-07-14:es用过冷热分离吗?假如现在有些数据热变冷,有些数据冷变热,怎么解决?
    2020-07-28:已知sqrt (2)约等于 1.414,要求不用数学库,求sqrt (2)精确到小数点后 10 位。
    2020-07-29:从 innodb 的索引结构分析,为什么索引的 key 长度不能太长?
    2020-07-27:如何设计一个分布式文件系统,如何设计动态扩容和数据定位?
    2020-07-26:如何用 socket 编程实现 ftp 协议?
    2020-07-25:如何实现一个高效的单向链表逆序输出?
  • 原文地址:https://www.cnblogs.com/Jenaral/p/5016726.html
Copyright © 2011-2022 走看看