block理解

block:https://www.jianshu.com/p/da96ec752aee

1.对于 block 外的变量引用,block 默认是将其复制到其数据结构中来实现访问的。也就是说block的自动变量截获只针对block内部使用的自动变量, 不使用则不截获, 因为截获的自动变量会存储于block的结构体内部, 会导致block体积变大。特别要注意的是默认情况下block只能访问不能修改局部变量的值。(block访问的值不会跟随外部的修改而变化---值传递)

2.当访问的变量为静态值(static)时,此时block内部引用局部变量是通过指针来访问的,所以外部的重新赋值,将导致block内变量的改变

对于用 __block 修饰的外部变量引用,block 是复制其引用地址来实现访问的。block可以修改__block 修饰的外部变量的值。(指针传递)

3。访问全局变量和访问静态值结果相同,全局变量存放在静态存储区,不同的时,全局变量是直接访问;

ARC下block属性的建议写法:
@property (strong, nonatomic) void (^block)(void);
@property (copy, nonatomic) void (^block)(void);

  以上的写法系统会自动帮我们将block从栈区拷贝到堆区;这样可以避免在调用block时,block访问的局部变量被释放后产生的异常;

  原因:一个局部变量加上__block修饰符后将变成了一个__Block_byref_val_0结构体类型的自动变量实例!!!!(此时局部变量和block是同一类型结构体)

  此时我们在block内部访问val变量则需要通过一个叫__forwarding的成员变量来间接访问val变量。

全局block相当于单例放在全局内存中;

Block不访问外界变量,放在代码段中,为全局块;

ARC 环境下:访问外界变量的 Block 默认存储在中(实际是放在栈区,然后ARC情况下自动又拷贝到堆区),自动释放。

Block的复制操作执行的是copy实例方法。Block只要调用了copy方法,栈块就会变成堆块。在ARC有效时,多次调用copy方法完全没有问题。

block的位置,只测试arc下:

 1 创建block对象后,在未使用局部变量时,赋值后的block位于全局区域(NSGlobalBlock), 引用局部变量后,block位于堆区 (NSMallockBlock);

对block只是声明对情况下,在未使用局部变量时,赋值后的block位于全局区域,

引用局部变量后,位于栈区;

注:在不确定block位于栈区或者堆区时,直接copy,保证block在堆区,再使用,避免crash;

使用__block后可以在block内部修改局部变量的理解:

参考:https://juejin.im/post/5ae40763f265da0ba062e842

当局部变量添加__block后,原生c代码会将基本数据类型变为一个struct,在使用block过程中,引用了此局部变量后,会将此struct复制到堆上,并且栈上的局部变量此时的struct中的__forwarding指向的是复制到堆上的struct上的变量的地址;而堆上的局部变量的struct中__forwarding则指向自己的变量;所以此时在block中修改局部变量值,block外部局部变量对应改变;

原文地址:https://www.cnblogs.com/hazhede/p/9925043.html