我们做一个测试,了解一下原理 代码如下:
- Stack (non-static) variables local to the enclosing lexical scope are captured as const variables.Their values are taken at the point of the block exPRession within the program. In nested blocks, the value is captured from the nearest enclosing scope.
-(void )test3 { NSString *_person2=@"person2"; NSMutableArray *_listTest=[[NSMutableArray alloc]init]; //初始值 NSLog(@"init _person2:%@,%p",_person2,_person2); NSLog(@"init _listTest:%@,%p",_listTest,_listTest); void (^myBlock)(int) = ^(int num) { //block内赋值 // _weakPerson2=@"person22"; NSLog(@"excuteing _person2:%@,%p",_person2,_person2); NSLog(@"excuteing _listTest:%@,%p",_listTest,_listTest); }; //修改前赋值 _person2=@"person22"; [_listTest addObject:@"1212"]; NSLog(@"excutebefore _person2:%@,%p",_person2,_person2); NSLog(@"excutebefore _listTest:%@,%p",_listTest,_listTest); myBlock(1); //block执行后 NSLog(@"excuteafter _person2:%@,%p",_person2,_person2); NSLog(@"excuteafter _listTest:%@,%p",_listTest,_listTest); }
输出一下结果:
2014-07-29 11:05:29.460 Test[2540:60b] init _person2:person2,0xb18ec 2014-07-29 11:05:29.463 Test[2540:60b] init _listTest:( ),0x17d98560 2014-07-29 11:05:29.464 Test[2540:60b] excutebefore _person2:person22,0xb193c 2014-07-29 11:05:29.465 Test[2540:60b] excutebefore _listTest:( 1212 ),0x17d98560 2014-07-29 11:05:29.467 Test[2540:60b] excuteing _person2:person2,0xb18ec 2014-07-29 11:05:29.468 Test[2540:60b] excuteing _listTest:( 1212 ),0x17d98560 2014-07-29 11:05:29.470 Test[2540:60b] excuteafter _person2:person22,0xb193c 2014-07-29 11:05:29.471 Test[2540:60b] excuteafter _listTest:( 1212 ),0x17d98560从日志可以看出:block内部对于可变、不可变的变量都无法修改,而且
struct __block_impl { void *isa; int Flags; int Reserved; void *FuncPtr; };
struct __KDBlockTest__test3_block_impl_0 { struct __block_impl impl; struct __KDBlockTest__test3_block_desc_0* Desc; NSString *_person2; NSMutableArray *_listTest; __KDBlockTest__test3_block_impl_0(void *fp, struct __KDBlockTest__test3_block_desc_0 *desc, NSString *__person2, NSMutableArray *__listTest, int flags=0) : _person2(__person2), _listTest(__listTest) { impl.isa = &_NSConcreteStackBlock; impl.Flags = flags; impl.FuncPtr = fp; Desc = desc; } };
//block实现的函数
static void __KDBlockTest__test3_block_func_0(struct __KDBlockTest__test3_block_impl_0 *__cself, int num) { NSString *_person2 = __cself->_person2; // bound by copy NSMutableArray *_listTest = __cself->_listTest; // bound by copy NSLog((NSString *)&__NSConstantStringImpl__var_folders_5l_2l25j3tn0wl_3zy1hpsq1rhc0000gp_T_KDBlockTest_6946c5_mi_4,_person2,_person2); NSLog((NSString *)&__NSConstantStringImpl__var_folders_5l_2l25j3tn0wl_3zy1hpsq1rhc0000gp_T_KDBlockTest_6946c5_mi_5,_listTest,_listTest); }
//block对象的描述信息(大小等等)
static struct __main1_block_desc_0 { size_t reserved; size_t Block_size; } __main1_block_desc_0_DATA = { 0, sizeof(struct __main1_block_impl_0)};
//这是objc测试函数test
static void _I_KDBlockTest_test3(KDBlockTest * self, SEL _cmd) { NSString *_person2=(NSString *)&__NSConstantStringImpl__var_folders_5l_2l25j3tn0wl_3zy1hpsq1rhc0000gp_T_KDBlockTest_6946c5_mi_1; NSMutableArray *_listTest=((id (*)(id, SEL))(void *)objc_msgSend)((id)((id (*)(id, SEL))(void *)objc_msgSend)((id)objc_getClass("NSMutableArray"), sel_registerName("alloc")), sel_registerName("init")); NSLog((NSString *)&__NSConstantStringImpl__var_folders_5l_2l25j3tn0wl_3zy1hpsq1rhc0000gp_T_KDBlockTest_6946c5_mi_2,_person2,_person2); NSLog((NSString *)&__NSConstantStringImpl__var_folders_5l_2l25j3tn0wl_3zy1hpsq1rhc0000gp_T_KDBlockTest_6946c5_mi_3,_listTest,_listTest); void (*myBlock)(int) = (void (*)(int))&__KDBlockTest__test3_block_impl_0((void *)__KDBlockTest__test3_block_func_0, &__KDBlockTest__test3_block_desc_0_DATA, _person2, _listTest, 570425344); _person2=(NSString *)&__NSConstantStringImpl__var_folders_5l_2l25j3tn0wl_3zy1hpsq1rhc0000gp_T_KDBlockTest_6946c5_mi_6; ((void (*)(id, SEL, id))(void *)objc_msgSend)((id)_listTest, sel_registerName("addObject:"), (id)(NSString *)&__NSConstantStringImpl__var_folders_5l_2l25j3tn0wl_3zy1hpsq1rhc0000gp_T_KDBlockTest_6946c5_mi_7); NSLog((NSString *)&__NSConstantStringImpl__var_folders_5l_2l25j3tn0wl_3zy1hpsq1rhc0000gp_T_KDBlockTest_6946c5_mi_8,_person2,_person2); NSLog((NSString *)&__NSConstantStringImpl__var_folders_5l_2l25j3tn0wl_3zy1hpsq1rhc0000gp_T_KDBlockTest_6946c5_mi_9,_listTest,_listTest); ((void (*)(__block_impl *, int))((__block_impl *)myBlock)->FuncPtr)((__block_impl *)myBlock, 1); NSLog((NSString *)&__NSConstantStringImpl__var_folders_5l_2l25j3tn0wl_3zy1hpsq1rhc0000gp_T_KDBlockTest_6946c5_mi_10,_person2,_person2); NSLog((NSString *)&__NSConstantStringImpl__var_folders_5l_2l25j3tn0wl_3zy1hpsq1rhc0000gp_T_KDBlockTest_6946c5_mi_11,_listTest,_listTest); }
简单分析block截获变量:
1).block初始化void (*myBlock)(int) = (void (*)(int))&__KDBlockTest__test3_block_impl_0((void *)__KDBlockTest__test3_block_func_0, &__KDBlockTest__test3_block_desc_0_DATA, _person2, _listTest, 570425344);
传入了参数:函数指针、block描述、外部变量 _person2 和 _listTest,这时候在block内部对 _person2、_listTest 进行了引用
: _person2(__person2), _listTest(__listTest)
_person2=(NSString *)&__NSConstantStringImpl__var_folders_5l_2l25j3tn0wl_3zy1hpsq1rhc0000gp_T_KDBlockTest_6946c5_mi_6; ((void (*)(id, SEL, id))(void *)objc_msgSend)((id)_listTest, sel_registerName("addObject:"), (id)(NSString *)&__NSConstantStringImpl__var_folders_5l_2l25j3tn0wl_3zy1hpsq1rhc0000gp_T_KDBlockTest_6946c5_mi_7);
2).执行block
((void (*)(__block_impl *))((__block_impl *)testBlock)->FuncPtr)((__block_impl *)testBlock);
其实还是调用了block对象里的函数对象(_block_imp1)的函数指针(FuncPtr) 所指向的函数__main1_block_func_0,并把block自己作为参数传递进去。
static void __KDBlockTest__test3_block_func_0(struct __KDBlockTest__test3_block_impl_0 *__cself, int num) { NSString *_person2 = __cself->_person2; // bound by copy NSMutableArray *_listTest = __cself->_listTest; // bound by copy NSLog((NSString *)&__NSConstantStringImpl__var_folders_5l_2l25j3tn0wl_3zy1hpsq1rhc0000gp_T_KDBlockTest_6946c5_mi_4,_person2,_person2); NSLog((NSString *)&__NSConstantStringImpl__var_folders_5l_2l25j3tn0wl_3zy1hpsq1rhc0000gp_T_KDBlockTest_6946c5_mi_5,_listTest,_listTest); }
总结:对于局部变量,变量不加__block修饰符,在block内部是无法修改变量的值。而且