首页 > 代码库 > [读书笔记]iOS与OS X多线程和内存管理 [Blocks部分-1]

[读书笔记]iOS与OS X多线程和内存管理 [Blocks部分-1]

第二章 Blocks

2.1 Blocks摘要

Blocks是C语言的扩充功能,是带有自动变量(局部变量)的匿名函数。
Blocks保存自动变量的值.
Blocks不是Objective-c独有的概念,在其他语言中(如Smalltalk或Ruby)也有对应的概念。

2.2 Blocks模式

2.2.1 Block语法
^ 返回值类型 参数列表 表达式
返回值类型可以省略
^ 参数列表 表达式
参数列表也可以省略
^ 表达式

2.2.2 Block类型变量
可将Block语法赋值给声明为Block类型的变量中。如:
int (^aBlock)(int)=^(int count){
return count+1;
};
也可以由Block类型变量向Block类型变量赋值,如
int(^bBlock)(int)=aBlock;
Block类型变量可作为函数参数,如
void func(int (^block)(int)){
}
Block类型变量作为函数返回值:
int (^func())(int){
return ^(int count){
return count+1;};
}
Block定义与函数指针定义类似,对比c语言中函数指针作为函数返回值理解:

指向函数的指针:可以仿照上边基本数据类型的定义
  例如:void (*p)() =function;    (funciton是某个定义好的函数) 
  格式:函数类型  *指针变量名 = 函数名;
     说明:由于p指针是指向函数的,所以(*p)()中的红色小括号必须有,因为函数本身是要参数的,即使没有参数也要写();
  如果p指向的函数有参数:int (*pp)(int, int) = sum;
  调用指向函数的指针:
     无参:p();  
     有参:int sum = pp(2,3);
block的定义和使用,和指向函数的指针格式很像
  例如:void (^firstBlock)() = ^(){...代码...};   说明:蓝色的小括号可以不写,有参数的时候必须写
  格式:block类型  ^block名称 = ^{代码段};
  有参数block:int (^multiBlock)(int, int) = ^(int a, int b){
               return a * b;
           };
  调用block:无参:firstBlock()
         有参:int result = multiBlock(2, 3);

函数指针作为函数返回值:
void (*fun1(double d))(int, char)
{
    printf("%f\n",d);
    return fun;
}

使用typedef可以使block在使用时更为简洁。
typedef int (^blk_t)(int);
我们可以对比一下:
void func(int (^block)(int)){} ——> void func(blk_t blk){}
int (^func())(int){}                  ——> blk_t func(){}

调用Block方法和调用C语言函数类似。
Block类型的变量完全可像C语言变量一样使用,因此可以使用指向Block类型变量的指针,即Block指针类型变量。
blk_t blk=^(int count){return count+1};
blk_t *blkptr=&blk;
(*blk_ptr)(10);

2.2.3 截获自动变量值

   int temp=2;
    void (^myBlk)(void)=^(){printf(“%d",temp);};
    temp=100;
    myBlk();
结果是 2;Block表达式截获所使用自动变量(局部变量)的值。

2.2.4 __block说明符
Block只能截获自动变量的瞬间值,并不能改变自动变量的值。想要在Block的表达式中将值赋给Block语法外声明的自动变量,需要在该变量前附加 __block说明符,该变量称为 __block变量;
   
 
__block int temp=2;
   
void (^myBlk)()=^(){
        temp+=
8;
    };
    myBlk();
    printf("----%d",temp);
2.2.5 截获的自动变量
截获自动变量的值是不能被修改的,但是截获OC对象(如NSMutableArray)时,向数组中增加元素是可以的,而直接赋值是不行的。也就是可以使用,不可以进行赋值。要进行赋值,同样需要添加__block修饰符。
在使用C语言数组时应注意,截获自动变量的方法并没有实现对C语言数组的截获。如下面代码:

constchar text[]="zyb";
   
void(^blk)(void)=^{
       
printf("%c",text[2]);
    };

会提示错误:Cannot refer to declaration with an array type inside block。可以使用指针解决该问题:
constchar *text="zyb";
   
void(^blk)(void)=^{
       
printf("%c",text[2]);
    };


[读书笔记]iOS与OS X多线程和内存管理 [Blocks部分-1]