1,为什么需要加__block

ARC环境下,一旦Block赋值就会触发copy,__block就会copy到堆上,Block也是__NSMallocBlock。ARC环境下也是存在__NSStackBlock的时候,这种情况下,__block就在栈上。ARC环境下,Block捕获外部对象变量,是都会copy一份的,地址都不同。只不过带有__block修饰符的变量会被捕获到Block内部持有。

MRC环境下,只有copy,__block才会被复制到堆上,否则,__block一直都在栈上,block也只是__NSStackBlock,这个时候__forwarding指针就只指向自己了。

int main(int argc, const char * argv[])

{ __block id block_obj = [[NSObject alloc]init];

id obj = [[NSObject alloc]init];

NSLog(@"block_obj = [%@ , %p] , obj = [%@ , %p]",block_obj , &block_obj , obj , &obj);

void (^myBlock)(void) = ^{

NSLog(@"***Block中****block_obj = [%@ , %p] , obj = [%@ , %p]",block_obj , &block_obj , obj , &obj);

};

myBlock();

return 0;

}

对于非对象的变量来说,

自动变量的值,被copy进了Block,不带__block的自动变量只能在里面被访问,并不能改变值。

带__block的自动变量 和 静态变量 就是直接地址访问。所以在Block里面可以直接改变变量的值。

而剩下的静态全局变量,函数参数,也是可以在直接在Block中改变变量值的,但是他们并没有变成Block结构体__main_block_impl_0的成员变量,因为他们的作用域大,所以可以直接更改他们的值。 静态全局变量,全局变量,函数参数他们并不会被Block持有,也就是说不会增加retainCount值。

对于对象来说 在MRC环境下,__block根本不会对指针所指向的对象执行copy操作,而只是把指针进行的复制。

而在ARC环境下,对于声明为__block的外部对象,在block内部会进行retain,以至于在block环境内能安全的引用外部对象。

block内部访问了对象类型的auto变量时:
1:如果block是在栈上,将不会对auto变量产生强引用(不管是 MRC 或者 ARC)
2:如果block是在堆上,就说明block进行过copy操作,进行copy操作的block会自动调用block内部的__main_block_copy_0函数,__main_block_copy_0函数内部会根据auto变量的修饰符形成相应的强引用(retain)或者弱引用.
3:当block销毁时,block会自动调用内部的dispose函数,dispose函数会自动调用内部的__main_block_dispose_0释放引用的auto变量.

 
  oc转c++源码查看:
 xcrun -sdk iphoneos clang -arch arm64 -rewrite-objc -fobjc-arc -fobjc-runtime=ios-8.0.0 MYBlock.m