__block修饰符的作用域问题
来源:互联网 发布:二分搜索算法流程图 编辑:程序博客网 时间:2024/05/21 17:08
~~~~我的生活,我的点点滴滴!!
我们知道,当在一个Block中想要访问这个Block之外的变量时,可以直接调用,但当我们想在Block中修改这个成员变量时,需要为这
个外部变量使用__block关键字进行声明,前面我们使用__block声明了一个基本数据类型int,那么我们在Block内成功将n改为了2:
#import <Foundation/Foundation.h>typedef int(^Sum)(int, int);int main(int argc, const char * argv[]){ @autoreleasepool { // insert code here... //NSLog(@"Hello, World!"); int n = 1; Sum sum = ^(int a, int b) { //n = 2; NSLog(@"n = %d", n); return (a+b) * n; }; NSLog(@"n = %d, result = %d", n, sum(5, 6)); } return 0;}
看看运行结果:
2015-04-29 08:23:12.186 blocktest[10816:303] n = 12015-04-29 08:23:12.188 blocktest[10816:303] n = 1, result = 11
不对啊!block里面打印的n=2,而外部打印的却是1,这是为什么呢?这说明使用__block修饰后的基本变量在block中的修改只对block中
有用,并不会真正改变这个变量的值!
此时会有人问:如果不把n声明为__block会怎么样了?如果没有添加关键字__block,block里面也能捕获到n的存在,只不过在里面不能更改n的值,
即此时要注释掉 n = 2,不然就会报错。
那么,对于基本变量如此,对于对象变量呢?我们再来试试:
新建一个测试对象:
TestObject.h
@interface TestObject : NSObject @property (nonatomic, retain) NSString * name; @end
TestObj.m
#import "TestObject.h" @implementation TestObject - (void)dealloc { NSLog(@"%@被销毁了!",self); [_name release]; [super dealloc];} @end
main.m
#import <Foundation/Foundation.h>#import "TestObject.h"typedef int(^Sum)(int, int);int main(int argc, const char * argv[]){ @autoreleasepool { // insert code here... //NSLog(@"Hello, World!"); int n = 1; Sum sum = ^(int a, int b) { //n = 2; NSLog(@"n = %d", n); return (a+b) * n; }; NSLog(@"n = %d, result = %d", n, sum(5, 6)); __block TestObject *obj = [[TestObject alloc] init]; obj.name = @"test out block"; NSString* (^Name)(TestObject *obj) = ^(TestObject *obj) { obj.name = @"test in block"; return obj.name; }; NSLog(@"%@", obj.name); NSLog(@"%@", Name(obj)); //加不加__block 都输出 "test in block" 说明改变了其值,block里面此用的是指针地址 NSLog(@"%@", obj.name); } return 0;}
这里我们在main函数中定义了一个TestObject对象,并调用setter方法更改name的属性。然后将TestObject对象传入一个名为Name的block中,
在block再调用setter方法修改name属性。再在外部打印返回值和TestObject对象的getter方法的值:结果如下:
2015-04-29 08:23:12.186 blocktest[10816:303] n = 12015-04-29 08:23:12.188 blocktest[10816:303] n = 1, result = 112015-04-29 08:23:12.188 blocktest[10816:303] test out block2015-04-29 08:23:12.189 blocktest[10816:303] test in block2015-04-29 08:23:12.189 blocktest[10816:303] test in blockProgram ended with exit code: 0
结果外部和内部的都是一样的,说明传入给block中的是对象的指针,指向的是同一个地址。既然传入的是同一个地址,那么说明这个对象指针
其实是没有变的,所以,其实不需要__block也可以的:
#import <Foundation/Foundation.h>#import "TestObject.h" int main(int argc, const char * argv[]){ @autoreleasepool { TestObject *obj = [[[TestObject alloc] init] autorelease]; obj.name = @"XCoder"; NSString * (^Name)(TestObject *) = ^(TestObject * myObj) { myObj.name = @"XCoder Studio"; return myObj.name; }; NSLog(@" In Block:%@", Name(obj)); NSLog(@"Out Block:%@", obj.name); } return 0;}
这样运行结果也是正确的!同样能得到上面的结果。
然而,如果我指针重新指向一个新的TestObject对象呢?
#import <Foundation/Foundation.h>#import "TestObject.h"typedef int(^Sum)(int, int);int main(int argc, const char * argv[]){ @autoreleasepool { // insert code here... //NSLog(@"Hello, World!"); // int n = 1;// // Sum sum = ^(int a, int b)// {// //n = 2;// // NSLog(@"n = %d", n);// // return (a+b) * n;// };// // NSLog(@"n = %d, result = %d", n, sum(5, 6)); TestObject *obj = [[TestObject alloc] init]; obj.name = @"test out block"; NSString* (^Name)(TestObject *obj) = ^(TestObject *obj) { obj = [[TestObject alloc] init]; obj.name = @"test in block"; return obj.name; }; NSLog(@"%@", obj.name); NSLog(@"%@", Name(obj)); NSLog(@"%@", obj.name); } return 0;}
我更改了指针指向,没有__block修饰,同样可以正常运行,不过运行结果不同:
2015-04-29 08:29:23.726 blocktest[10855:303] test out block2015-04-29 08:29:23.726 blocktest[10855:303] test in block2015-04-29 08:29:23.727 blocktest[10855:303] test out blockProgram ended with exit code: 0
由于block里面重新申请了内存,所以此时已经不指向同一个地址了,当然无法改变外部obj.name的值。
总的说明一点儿,__block修饰符只是针对基本数据类型,对于对象类型就无法适用!
结尾补充一张块的表示图,简单理解块就是C语言中的回调函数。
0 0
- __block修饰符的作用域问题
- 黑幕背后的__block修饰符
- 黑幕背后的__block修饰符
- 黑幕背后的__block修饰符
- __weak与__block修饰符的区别
- 黑幕背后的__block修饰符
- 黑幕背后的__block修饰符
- 黑幕背后的__block修饰符
- 黑幕背后的__block修饰符
- __block和__weak修饰符的区别
- 黑幕背后的__block修饰符
- 黑幕背后的__block修饰符
- __block和__weak修饰符的区别?
- 黑幕背后的__block修饰符
- 修饰符作用域的问题
- __block的作用
- __block修饰符个人理解
- 你真的理解__block修饰符的原理么?
- Cocos2d-x3.2与OpenGL渲染总结Cocos2d-x3.2的渲染流程
- 【C#/.Net】.Net引用web,并提取SQL数据
- jQuery实现商品飞入购物车效果插件
- CRC16校验
- 黑马程序员+Java一对一映射问题的探索
- __block修饰符的作用域问题
- 用GDB调试程序(五)
- IOS高级动画详解
- IntelliJ IDEA 常用快捷键
- 算法导论2学习整理
- 学习ASP .NET MVC5官方教程总结目录
- maven学习笔记-01-基本概念篇
- CheckBox全选实现
- 在windows上如何安装部署设置SVN服务器