如何使用Block来修改外部变量

2017-02-20  本文已影响0人  俊俊吖

我们都知道:block 是不允许修改外部变量的,这里所说的外部变量的值,指得是栈中指针的内存地址。__Block 的作用是只要观察到该变量被被Block所持有,就将"外部变量"在栈中的内存地址放到了堆中。进而在Block内部也可以修改外部变量的值。

1.例如:修改基本数据类型值中的Int 类型(浮点型一样的道理)

-(void)testBlock{

__block

int a =0;

NSLog(@"定义前:%p,a ===%d",&a,a);

void(^foo)(NSString*name) = ^(NSString*str){

a =1;

NSLog(@"block内部,a ====%d :%p",a,&a);

};

foo(@"1111");

NSLog(@"定以后:%p,a === %d",&a,a);

}

运行结果如下:

NewCocoTest[1316:35458]定义前:0x7fff56bdc7b8,a ===0

2017-02-20 10:12:16.867 NewCocoTest[1316:35458] block内部,a ====1 :0x600000033998

2017-02-20 10:12:16.867 NewCocoTest[1316:35458]定以后:0x600000033998,a === 1

加上__Block 以后就产生了浅拷贝,内存地址由原来的栈区,变成了堆区。

2.修改基本数据类型中的char 类型

例子:

-(void)testBlockTwo{

NSMutableString*a = [NSMutableStringstringWithFormat:@"Tom"];

NSLog(@"定义以前a指向的堆中地址;%p,a在栈中的指针地址:%p,a ======%@",a,&a,a);

void(^foo)(void) = ^{

a.string=@"Jeery";

NSLog(@"block内部a指向的堆中地址:%p,a在栈中的指针地址%p,a ======%@",a,&a,a);

};

foo();

NSLog(@"Block以后a在堆中的地址%p,a在栈中的指针地址%p,a ======%@",a,&a,a);

}

运行结果如下:

NewCocoTest[1316:35458]定义以前a指向的堆中地址;0x608000275e80,a在栈中的指针地址:0x7fff56bdc7b8,a ======Tom

2017-02-20 10:12:16.868 NewCocoTest[1316:35458] block内部a指向的堆中地址:0x608000275e80,a在栈中的指针地址0x600000045f30,a ======Jeery

2017-02-20 10:12:16.868 NewCocoTest[1316:35458] Block以后a在堆中的地址0x608000275e80,a在栈中的指针地址0x7fff56bdc7b8,a ======Jeery

这里的a已经由基本数据类型,变成了对象类型。block会对对象类型的指针进行copy,copy到堆中,但并不会改变该指针所指向的堆中的地址,block体内修改的实际是a指向的队中的内容。

总结:Block不允许修改外部变量的值,其实是不允许修改栈中指针的内存地址。如果将变量的栈中内存地址放到堆中,栈区是不能修改,堆区才能修改

上一篇下一篇

猜你喜欢

热点阅读