1.关于Obeject C中block的使用语法
举例如下:
-(void) test{
//声明一个返回值为long的,有两个入参且其中一个是long类型一个是bool类型的,名字叫做myblock的块
long ^myblock(long,bool);
//定义该block块
myblock = ^(long i, bool flag){
if(flag == true){
NSLog("the number is:%d", i);
return i;
}else{
NSLog("the number is:%d",i+1);
return i+1;
}
}
//直接调用块来使用
long k = myblock(1.0, false);
//或者作为其他函数的参数来使用
[self functionWithBlock:myblock];
//当作为其他函数参数来使用的时候,可以直接在调用的时候才进行声明定义
[self functionWithBlock:^(long i, bool flag){
if(flag == true){
NSLog("the number is:%d", i+1);
return i+1;
}else{
NSLog("the number is:%d",i+2);
return i+2;
}
}]
}
-(void) functionWithBlock: (long (^)(long i, bool flag) block)
{
//具体实现
long i = 3;
bool flag = true;
block(i, flag);
}
2.当block中需要用到block外的变量的时候(注意这里的用到是指仅仅作为使用该值,而非进行修改),对于普通的block外的变量,那么block在定义的时候就会把这个变量拷贝一份至自己block块所对应的内存中作为一个常量,即使在外部这个变量后续变了,那么block内所用到的这个变量也一直不变,但是若这个外部变量是static修饰,则block块不会拷贝,而是直接用该值,即后续外部这个变量后续变了,那么block内所用到的这个变量也会跟着改变,举例如下:
-(void) test{
long arg = 1.0;
long normalOutV = 5;
static long staticOutV = 5;
__block long blockOutV = 5;
//声明一个返回值为long的,有一个入参且是long类型的,名字叫做myblock的块
long ^myblock(long);
//定义该block块
myblock = ^(long i){
NSLog("the normalOutV plus i is :%ld", normalOutV+i);
NSLog("the staticOutV plus i is :%ld", staticOutV+i);
NSLog("the blockOutV plus i is :%ld", blockOutV+i);
}
//第一次调用
//第一次调用分别输出6,6,6
//????block修饰的block外的变量具体怎样没验证过..只是猜测...
myblock(arg);
//修改外部变量的值
normalOutV++;
staticOutV++;
blockOutV++;
//修改后第二次调用
//第二次调用分别输出6,7,7
//????block修饰的block外的变量具体怎样没验证过..只是猜测...
myblock(arg);
}
当block中需要修改block外变量的值的时候,需要将这个变量用block 修饰,不然将会报错,因为如前面所说,block用到block外的普通变量的时候,本质是拷贝一份值至自己内存空间作为一个常量存储,所以不允许修改,但是用block就代表了block内使用block外的那个变量时还是到其本身所在的内存区域去寻址.
-(void) test{
long arg = 1.0;
long normalOutV = 5;
static long staticOutV = 5;
__block long blockOutV = 5;
//声明一个返回值为long的,有一个入参且是long类型的,名字叫做myblock的块
long ^myblock(long);
//定义该block块
myblock = ^(long i){
normalOutV+=i;//报错,编译通不过
staticOutV+=i;//这个不确定...有待验证...
blockOutV+=i;//这个是正确的
}
}
3.关于block对象在内存中的位置,因为比较复杂,网上也有好多讲解,其实我自己本身听着也是模棱两可,所以这里就不做具体讲解,只是说几点我自己的理解:
首先,block代码块本质上可以看作是一种特殊的伪对象,为什么叫伪对象,因为正常来说,对象实际存在的内存是在堆中,但是像前面所举的几个block的例子,他们所对应的对象是在栈中的,随着test方法结束之后而自动被回收(注意,这里的回收跟ARC没有半毛钱关系),这种block被称为"NSStackBlock".但是如果把这个block对象执行了copy操作,那么copy之后返回的新block则是在堆中了,这个时候只能依靠release操作或者让ARC来自动回收内存空间了,这种block被叫做NSMallocBlock.看网上说还有一种block类型叫做NSGlobalBlock,说是当block里面没有局部变量的时候会block会变为这个类型,有点不理解,也不知道他到底是存在内存里哪个区域,静态区?还是别的..有待研究.