1 关于__block变量为什么可以在block体内修改值
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
void foo(){ __block int i = 1024;//此时i在栈上 int j = 1;//此时j在栈上 void (^blk)(void); blk = ^{printf("%d, %d\n", i, j); };//此时,blk已经初始化,它会拷贝没有__block标记的常规变量自己所持有的一块内存区,这块内存区现在位于栈上,而对于具有__block标记的变量,其地址会被拷贝置前述的内存区中 blk();//1024, 1 void(^blkInHeap)(void) = Block_copy(blk);//复制block后,block所持有的内存区会被拷贝至堆上,此时,我们可以说,这个block现在位于堆上 blkInHeap();//1024,1 i++; j++; blk();//1025,1 blkInHeap();//1025,1} |
让我们一步步剖析:
首先,我们在栈上创建了变量ij,并赋予初始值,然后创建一个block变量名为blk,但未赋值。
然后我们初始化这个blk,赋值为一个只有一句printf的block,值得注意的是,一个block一旦创建,其引用到的常规变量会进行如下操作:
没有__block标记的变量,其值会被复制一份到block私有内存区
有__block标记的变量,其地址会被记录在block私有内存区
然后调用blk,打印1024, 1很好理解
接下来复制blk到堆,名曰blkInHeap,调用之,打印1024, 1也很好理解
接下来我们为ij增值,使其变为1025和2,此时再调用blk或者blkInHeap,会发现结果为1025, 1,这是因为变量j早已在创建原始的block时,被赋值进block的私有内存区,后续对i的操作并非操作的私有内存区的复制品,当调用blk或者blkInHeap时,其打印使用的是私有内存区的复制品,故而打印结果依旧为1;而变量j的修改会实时生效,因为block记录的是它的地址,通过地址来访问其值,使得外部对j的修改在block中得以生效。
2 关于使用
转载自:http://fuckingblocksyntax.com/
returnType (^blockName)(parameterTypes) = ^returnType(parameters) {...};
@property (nonatomic, copy) returnType (^blockName)(parameterTypes);
- (void)someMethodThatTakesABlock:(returnType (^)(parameterTypes))blockName;
[someObject someMethodThatTakesABlock:^returnType (parameters) {...}];
typedef returnType (^TypeName)(parameterTypes);
TypeName blockName = ^returnType(parameters) {...};
原文:http://www.cnblogs.com/HypeCheng/p/4595504.html