block变量捕获
- 局部变量会被捕获
1.带auto修饰的,(默认创建的变量都会自带Auto)会进行值捕获,因为局部变量在大括弧结束的地方就会被释放掉,所以直接进行值捕获,这样后面就算这个值被修改,或者释放掉,都不会影响block里面的值
2,用static修饰的局部变量会进行地址捕获,因为这个值不会被释放,会一直在内存中,所以捕获地址,这样这个值如果后面进行了更改,会影响block里面,因为是通过地址去取的值
3.每个方法都会默认带两个参数,一个是self,一个是cmd,这也是为什么每个方法里面都可以调用Self和cmd的原因,所以在方法里self是参数,是局部变量,肯定会进行捕获,地址捕获,如果里面有调用成员变量,方法,也需要捕获self,因为需要通过self去找到成员变量,去发送消息,调用方法 - 全局变量不会被捕获
全局变量在哪里都可以被调用,不需要去捕获,在调用的地方直接去取就可以了 - block内部有isa指针,所以说其本质也是OC对象
block类型
- globalblock全局block,没有访问auto变量的block都是全局block,对globalblock进行copy.什么都不会做,没有意义
- stackblock 栈block,访问了auto的,都是,栈block因为是被系统自动管理,所以里面的内存很可能被销毁
- mallocblock堆block,通过copy栈block得到堆block,内存由程序员自己管理,如果对堆block进行copy会让引用计数加一
block只要在栈上面,都不会对auto变量产生强引用,因为没必要,栈上的内存随时会被释放掉
mrc下如果用strong修饰,不会进行将block从栈拷贝到堆的操作,arc下,strong和copy一样,都会进行从栈到堆的操作,所以两个没有什么区别




1、局部变量截获 是值截获。
NSInteger num = 3;
NSInteger(^block)(NSInteger) = ^NSInteger(NSInteger n){
return n*num;
};
num = 1;
NSLog(@"%zd",block(2));
在里面修改num会报错
局部对象变量也是一样,比如
NSMutableArray * arr = [NSMutableArray arrayWithObjects:@"1",@"2", nil];
void(^block)(void) = ^{
NSLog(@"%@",arr);//局部变量
[arr addObject:@"4"];
};
[arr addObject:@"3"];
arr = nil;
block();
最后打印为 1,2,3,block后面的操作,不影响原先保存的值
2、局部静态变量截获 是指针截获。
3、全局变量,静态全局变量截获:不截获,直接取值。
局部变量被编译成值形式,而静态变量被编成指针形式,全局变量并未截获。而__block修饰的变量也是以指针形式截获
该对象有个属性:num5,即我们用__block修饰的变量。
这里__forwarding是指向自身的(栈block)。
一般情况下,如果我们要对block截获的局部变量进行赋值操作需添加__block
修饰符,而对全局变量,静态变量是不需要添加__block修饰符的。
另外,block里访问self或成员变量都会去截获self。
三、Block的几种形式
分为全局Block(_NSConcreteGlobalBlock)、栈Block(_NSConcreteStackBlock)、堆Block(_NSConcreteMallocBlock)三种形式
其中栈Block存储在栈(stack)区,堆Block存储在堆(heap)区,全局Block存储在已初始化数据(.data)区
1、不使用外部变量的block是全局block
2、使用外部变量并且未进行copy操作的block是栈block
3、对栈block进行copy操作,就是堆block,而对全局block进行copy,仍是全局block
网友评论