Block对捕捉变量的影响
来源:互联网 发布:js实现幻灯片效果 编辑:程序博客网 时间:2024/05/16 06:09
以前只知道block可以捕捉环境中的变量并且会拷贝该变量,但是是深拷贝还是浅拷贝呢?对于这个问题一直很模糊,今天用几个例子来研究一下这个问题。
先看个例子1:
NSMutableArray *array = [NSMutableArray arrayWithObjects:@"1",@"2", nil]; NSLog(@"之前 - %p", array); void (^block)() = ^{ NSLog(@"之后 - %p", array); }; block(); 2015-11-11 13:12:34.252 俩个在不同文件中相同名称函数会冲突[1595:122276] 之前 - 0x7f8e11430fe02015-11-11 13:12:34.253 俩个在不同文件中相同名称函数会冲突[1595:122276] 之后 - 0x7f8e11430fe0
可以发现对象的地址没有变,也就是block没有改变对象。
例子2 :
NSMutableArray *array = [NSMutableArray arrayWithObjects:@"1",@"2", nil]; NSLog(@"之前 - %p", &array); void (^block)() = ^{ NSLog(@"之后 - %p", &array); }; block();2015-11-11 13:19:05.271 俩个在不同文件中相同名称函数会冲突[1627:126081] 之前 - 0x7fff5045c9182015-11-11 13:19:05.272 俩个在不同文件中相同名称函数会冲突[1627:126081] 之后 - 0x7fde4bc68400
可以发现引用对象的指针发生改变了。
小结:block会对外部局部变量进行浅拷贝,然后在block体内使用该副本。
例子3:改变array指针指向,再调用块,会输出原数组对象还是新的数组对象呢?
NSMutableArray *array = [NSMutableArray arrayWithObjects:@"1",@"2", nil]; void (^block)() = ^{ NSLog(@"%@", array); }; block(); array = [NSMutableArray arrayWithObjects:@"3", @"4", nil]; block();2015-11-11 13:22:46.342 俩个在不同文件中相同名称函数会冲突[1647:128664] ( 1, 2)2015-11-11 13:22:46.343 俩个在不同文件中相同名称函数会冲突[1647:128664] ( 1, 2)
根据上面俩个例子得出的小结很容易解释,block体内和外的array是俩个指针,改变体外的指针自然不会影响到体内的指针了,而体内的指针指向的是原array对象,所以输出是原对象。
例子4 :在例子3中,如果改变对象,那么应该会对输出产生影响吗?
NSMutableArray *array = [NSMutableArray arrayWithObjects:@"1",@"2", nil]; void (^block)() = ^{ NSLog(@"%@", array); }; block(); [array addObject:@"3"]; block();2015-11-11 13:35:39.823 俩个在不同文件中相同名称函数会冲突[1675:133524] ( 1, 2)2015-11-11 13:35:39.824 俩个在不同文件中相同名称函数会冲突[1675:133524] ( 1, 2, 3)
可以看到输出改变了。
例子5 :
- (void)viewDidLoad { [super viewDidLoad]; NSMutableArray *array = [NSMutableArray arrayWithObjects:@"1",@"2", nil]; NSLog(@"之前 - %p %@", array, array); void (^block)() = ^{ NSLog(@"之后 - %p %@", array, array); }; self.block = block; [self test];}- (void)test{ self.block();}2015-11-11 13:49:59.540 俩个在不同文件中相同名称函数会冲突[1752:140238] 之前 - 0x7f83db43b9e0 ( 1, 2)2015-11-11 13:49:59.541 俩个在不同文件中相同名称函数会冲突[1752:140238] 之后 - 0x7f83db43b9e0 ( 1, 2)
从这个例子中可以看出,block持有了对象(引用计数+1)。因为,array是局部变量,所以viewDidLoad执行完后该变量会被释放,由于默认局部变量是__strong,变量释放的同时对象引用计数-1,但是例子中看到在test方法中数组对象没有“死”,所以可以推测block对其引用计数+1。
总结 :block只会对外部局部变量进行浅拷贝,并在体内使用该拷贝的指针,不会拷贝对象本身,但是会持有对象(引用计数+1)。也就是说除非对象本身改变了,否则外部局部变量的改变是影响不到block体内的。这也就是为什么block叫做闭包,屏蔽外界对内的影响。
之前一直说的是局部变量,如果是全局变量(成员变量)进入block会怎么样呢?
例子6:
_array = [NSMutableArray arrayWithObjects:@"1",@"2", nil]; NSLog(@"之前 - %p %@", &_array, _array); void (^block)() = ^{ NSLog(@"之后 - %p %@", &_array, _array); }; block();2015-11-11 14:06:00.699 俩个在不同文件中相同名称函数会冲突[1819:147698] 之前 - 0x7ffb8a5a9068 ( 1, 2)2015-11-11 14:06:00.700 俩个在不同文件中相同名称函数会冲突[1819:147698] 之后 - 0x7ffb8a5a9068 ( 1, 2)
地址一样,所以block体的内外全局变量是同一个。这也提醒以后在block中使用全局变量,要注意全局变量会破坏block的封闭性(全局变量的改变会影响到block体内的运算)。
- Block对捕捉变量的影响
- 注意block中变量捕捉的问题
- Static 对变量的影响
- static局部变量对性能的影响
- 绑定变量对性能的影响
- 直方图对绑定变量sql的影响
- 32,static对局部变量的影响
- block 对外部引用变量的处理
- block 对外部引用变量的处理
- 局部的变量与成员变量对线程的影响
- JAVA 多线程对成员变量与局部变量的影响
- 【学习总结】关于magin padding对block、inline、inline-block 元素的影响
- 同名的全局变量和局部变量对程序的影响
- block代码块对变量的处理的一些看法
- setjmp 和 longjmp,以及对变量的影响
- switch case、goto对变量定义的影响
- java基础-finally块对return变量的影响分析
- JAVA局部变量对垃圾回收的影响
- Scala 实现两个类型比较的实现
- 【记录学习linux】第一天
- 反向传播神经网络极简入门
- cocos2d-x之JS中的Android按键监听
- strlen函数,strcat函数,strcpy函数,strncpy函数,strcmp函数
- Block对捕捉变量的影响
- 舍得不曾舍得的舍得会舍得,习惯不曾习惯的习惯会习惯!
- java jni 入门5 - 编码签名 以及 javap命令的使用
- sublime快捷键整理
- Android 动画
- 搬家到CSDN
- AWK用户自定义函数
- Activity 在本地进程的创建流程,已经动画
- ASIHTTPRequest