Block总结
2016-01-20 19:16
204 查看
Block, 简单的说,就是一个函数对象,和其它类型的对象一样,你可以创建它,可以赋给一个变量,也可以作为函数的参数来传递。
block和函数指针有点类似,但是不完全一样。block是在程序运行过程中产生的,在一个作用域中生成的block对象分配在栈上(stack),和其它所有分配在栈上的对象一样,离开这个作用域就不存在了。函数指针是一个函数的地址,他不存在作用域(或者说上下文)。换句话说,block既实现了函数的功能,还能携带函数的执行环境。
先看一个xcode文档中的错误案例:
void dontDoThis() {
void (^blockArray[3])(void); // an array of 3 Block references,这个作用域内block已经不存在喽!
for (int i = 0; i < 3; ++i) {
blockArray[i] = ^{ printf("hello, %d\n", i); };
// WRONG: Block literal scope is "for loop" //出了作用域是不可以使用的,这点跟C++中的函数指针差别比较大
}
}
另外,block对象在一个作用域中,在这个block中可以访问同在这个作用域中的本地变量。下面是一个例子:
void say(NSString *something)
{
NSArray * array = [NSArray arrayWithObjects:@"tom", @"jerry", @"robin", nil];
[array each:^(id obj) {
NSLog(@"%@, %@", something, obj);
}];
}
block对象在该对象产生时,对当时的栈变量进行只读拷贝,这些变量在之后修改,并不对该block执行时使用的值造成影响。
下面是一段实例代码:
{
int outA = 8;
int (^myPtr)(int) = ^(int a){ return outA + a;}; //block里面可以读取同一类型的outA的值
outA = 5; //在调用myPtr之前改变outA的值
int result = myPtr(3); // result的值仍然是11,并不是8
NSLog(@"result=%d", result);
}
值得注意的是,这里copy的是变量的值,如果它是一个指针,它的值是可以在block里被改变的。如下代码:
{
NSMutableArray *mutableArray = [NSMutableArray arrayWithObjects:@"one", @"two", @"three", nil];
int result = ^(int a){[mutableArray removeLastObject]; return a*a;}(5);
NSLog(@"test array :%@", mutableArray);
}
block内,可以直接读写static变量值,如下代码:
{
static int outA = 8;
int (^myPtr)(int) = ^(int a){ outA = 5; return outA + a;};
int result = myPtr(3); //result的值是8,因为outA是static类型的变量
NSLog(@"result=%d", result);
}
block内部可以读写block variable类型的变量,如下代码:
{
__block int num = 5;
int (^myPtr)(int) = ^(int a){return num++;};
int (^myPtr2)(int) = ^(int a){return num++;};
int result = myPtr(0); //result的值为5,num的值为6
result = myPtr2(0); //result的值为6,num的值为7
NSLog(@"result=%d", result);
}
block在内存中的位置分为三种类型:NSGlobalBlock,NSStackBlock,NSMallocBlock
应该是mrc和arc机制还不一样,头疼呀
block和函数指针有点类似,但是不完全一样。block是在程序运行过程中产生的,在一个作用域中生成的block对象分配在栈上(stack),和其它所有分配在栈上的对象一样,离开这个作用域就不存在了。函数指针是一个函数的地址,他不存在作用域(或者说上下文)。换句话说,block既实现了函数的功能,还能携带函数的执行环境。
先看一个xcode文档中的错误案例:
void dontDoThis() {
void (^blockArray[3])(void); // an array of 3 Block references,这个作用域内block已经不存在喽!
for (int i = 0; i < 3; ++i) {
blockArray[i] = ^{ printf("hello, %d\n", i); };
// WRONG: Block literal scope is "for loop" //出了作用域是不可以使用的,这点跟C++中的函数指针差别比较大
}
}
另外,block对象在一个作用域中,在这个block中可以访问同在这个作用域中的本地变量。下面是一个例子:
void say(NSString *something)
{
NSArray * array = [NSArray arrayWithObjects:@"tom", @"jerry", @"robin", nil];
[array each:^(id obj) {
NSLog(@"%@, %@", something, obj);
}];
}
block对象在该对象产生时,对当时的栈变量进行只读拷贝,这些变量在之后修改,并不对该block执行时使用的值造成影响。
下面是一段实例代码:
{
int outA = 8;
int (^myPtr)(int) = ^(int a){ return outA + a;}; //block里面可以读取同一类型的outA的值
outA = 5; //在调用myPtr之前改变outA的值
int result = myPtr(3); // result的值仍然是11,并不是8
NSLog(@"result=%d", result);
}
值得注意的是,这里copy的是变量的值,如果它是一个指针,它的值是可以在block里被改变的。如下代码:
{
NSMutableArray *mutableArray = [NSMutableArray arrayWithObjects:@"one", @"two", @"three", nil];
int result = ^(int a){[mutableArray removeLastObject]; return a*a;}(5);
NSLog(@"test array :%@", mutableArray);
}
block内,可以直接读写static变量值,如下代码:
{
static int outA = 8;
int (^myPtr)(int) = ^(int a){ outA = 5; return outA + a;};
int result = myPtr(3); //result的值是8,因为outA是static类型的变量
NSLog(@"result=%d", result);
}
block内部可以读写block variable类型的变量,如下代码:
{
__block int num = 5;
int (^myPtr)(int) = ^(int a){return num++;};
int (^myPtr2)(int) = ^(int a){return num++;};
int result = myPtr(0); //result的值为5,num的值为6
result = myPtr2(0); //result的值为6,num的值为7
NSLog(@"result=%d", result);
}
block在内存中的位置分为三种类型:NSGlobalBlock,NSStackBlock,NSMallocBlock
应该是mrc和arc机制还不一样,头疼呀
相关文章推荐
- android WindowManager解析与骗取QQ密码案例分析
- kill常用
- BCSP 剖析(二)- BCSP link establish过程
- 【慕课笔记】第三章 常用的运算符 第6节 JAVA中的条件运算符
- jQuery Form 表单提交插件-----ajaxSubmit() 的应用
- shell脚本执行查找进程,然后查杀进程
- 变量和基本类型二
- 问题思考方法
- 关于UIimage的一些注释
- 布局细节问题
- 导航控制器内部跳转
- Entity Framework 6 Recipes 2nd Edition(10-2)译 -> 返回输出参数
- Project Euler 106:Special subset sums: meta-testing 特殊的子集和:元检验
- 一个字符编码引起的血案
- 【maven基础】Eclipse中Maven安装与配置
- Rabbit and Grass(杭电1849)(尼姆博弈)
- 沈剑:58同城数据库架构最佳实践
- 光标事件之focus()与select()
- Mybatis动态sql和sql片段
- moon 26 监听器