http://blog.csdn.net/menxu_work/article/details/8762848

block(代码块)的介绍以及使用方法和变量之间的关系

标签: block
2013-04-05 22:52 5613人阅读 评论(0) 收藏 举报
 分类:
ios(72)   object-c(66) 
 

目录(?)[+]

 

Block是什么?

Block是C语言的一个语法特性,同时也是C语言的运行时特性,它很像C中的函数指针,因为你可以像使用函数指针一样的去使用block对象;它也很像C++中的函数对象,因为除了要执行的代码,block还可以携带和block绑定的状态信息。

因此,block是一个对象,这个对象里包含了要执行的代码片段以及一些状态信息。

MacOSX 10.6和iOS 4.0以上版本的Xcode开发包提供了对block的支持。

Block的功能

block是一片具有以下特性的内联代码片段集合:

  • 可以像函数一样有类型参数;
  • 可以声明或推算出一个返回类型;
  • 可以访问和block定义在同一个词法范围里的变量(即Status);
  • 可以修改同一个词法范围里的变量;
  • 同一个词法范围的block之间可以共享变量和变量的修改结果;
  • 当栈被摧毁后,栈里的block依旧可以保持状态信息;

Block的用法

作为一个自包含的代码片段,由于以下特性,block很适合作为回调函数的替代方案:

  • 你可以在方法的下上文中,调用block的地方直接编写构成block的代码片段;
  • block可以访问局部变量;

如何声明和定义Block

你可以通过^操作符定义一个block类型的变量,用{}来圈定block的代码片段,如下图所示:

再次声明:block可以访问和block定义在同一个词法范围里的变量。

int multiplier = 7;
int (^myBlock)(int) = ^(int num) { return num * multipiler; } printf("%d", myBlock(3)); // prints "21"

直接使用Block

在更多的时候,你并不需要定义自己的Block类型,而是在API中直接编写block代码片段,例如:qsort_b。

char *myCharacter[3] = { "safari", "ie", "chrome" };
qsort_b(myCharacter, 3, sizeof(char *), ^(const void *l, const void *r) {
    char *left = *(char **)l;
    char *right = *(char **)r;
    return strncmp(left, right, 1);
});

Block和Cocoa

Cocoa framework中很多方法使用了Block作为其参数(尽管也有对应的callback版本,但还是推荐使用 block版本)。在动画以及集合遍历方面,block很常见。

NSArray *stringsArray = [NSArray arrayWithObjects:
                                 @"string 1",
                                 @"String 21",
                                 @"string 12",
                                 @"String 11",
                                 @"String 02", nil];
static NSStringCompareOptions comparisonOptions = NSCaseInsensitiveSearch |
    NSNumericSearch |NSWidthInsensitiveSearch | NSForcedOrderingSearch; NSLocale *currentLocale = [NSLocale currentLocale];
NSComparator finderSortBlock = ^(id string1, id string2) {
    NSRange string1Range = NSMakeRange(0, [string1 length]);
    return [string1 compare:string2
                    options:comparisonOptions
                      range:string1Range
                     locale:currentLocale];
}; NSArray *finderSortArray = [stringsArray
    sortedArrayUsingComparator:finderSortBlock]; NSLog(@"finderSortArray: %@", finderSortArray);

block和变量之间的关系

这一部分涉及内存管理相关的内容,为了正确的使用block,理解并记住它们,很重要:

在一个block代码片段的内部,你可以使用三种不同类型的变量(就像你在函数里一样):

  • 全局变量(包括static locals);
  • 全局函数(尽管这并不是变量=。=);
  • 在包含block的词法范围内的局部变量;

当在一个Block里使用变量时,应遵循以下规则:

  • 在包含block的词法范围里的栈局部变量,在block内部是常量,只能只读访问。这些局部变量的值即block执行时,局部变量的值。在多层内嵌的block中,

局部变量的值,取最内层词法范围里,局部变量的值;

  • 被声明为__block存储类型的局部变量通过引用传递给block,因此是mutable的;在__block类型的局部变量的有效范围内,对该局部变量的修改,会在该有效范围内的所有block范围内生效;
  • 定义在block内部的局部变量,和函数内部的局部变量法则相同;

正确的:

int x = 123;
void (^printXandY)(int) = ^(int y) {
    printf("%d %d\n", x, y);
}; printXandY(456);

错误的:

int x = 123;

void (^printXandY)(int) = ^(int y) {
    x = x + y; // ERROR HERE!!! x should be __block
    printf("%d %d\n", x, y);
}; printXandY(456);

关于__block的进一步讨论

  1. __block是只针对局部变量生效的一种描述变量存储类型的关键字,因此__block类型的变量都是栈变量;
  2. __block类型的变量在其定义的语法范围里,和该范围内的所有block共享存储空间,当block在被复制到heap区域时,同区域内的__block变量占用的内存不会随着退栈而销毁;
  3. 出于优化的考虑,栈中的block对象最开始和一般的栈局部变量是相同的,当使用Block_copy对block进行复制时,才被拷贝到heap区域;
  4. __block变量不能是一个可变长数组;

下面这个例子用于展示,各种类型的变量与__block之间的交互:

extern NSInteger CounterGlobal;
static NSInteger CounterStatic;
{
    NSInteger localCounter = 42;
    __block char localCharacter;
    void (^aBlock)(void) = ^(void) {
        ++CounterGlobal;
        ++CounterStatic;
        CounterGlobal = localCounter; // localCounter fixed at block creation
        localCharacter = 'a'; // sets localCharacter in enclosing scope
    };
    ++localCounter; // unseen by the block
    localCharacter = 'b';
    aBlock(); // execute the block
    // localCharacter now 'a'
}

__block和Object C对象之间的关系

如果,你在一个方法的实现里,使用了__block,则:

  • 通过引用的方式访问对象的,self被retain;

    dispatch_async(queue, ^{
        // instanceVariable is used by reference, self is retained
        doSomethingWithObject(instanceVariable);
    });
  • 通过值访问对象的,被访问的对象被retain;

    id localVariable = instanceVariable;
    dispatch_async(queue, ^{
        // localVariable is used by value, localVariable is retained (not self)
        doSomethingWithObject(localVariable);
    });

__block和C++对象之间的关系

需要注意两点:

  • 把一个基于栈的C++对象变成一个__block类型的时候,要调用类的copy constructor;
  • 在block内部使用栈中的C++对象时,要调用栈的const copy constructor;
Comment by project member SuPeiqi....@gmail.com, Mar 10, 2011

change :

int (myBlock)(int) = (int num) { return num ^ multipiler; }

to :

int (myBlock)(int) = (int num) { return num *  multipiler; }

来自:http://code.google.com/p/nevel-mercury/wiki/GetFamiliarWithBlock
 
 

block(代码块)的介绍以及使用方法和变量之间的关系的更多相关文章

  1. block代码块介绍

    关于block的简单介绍 什么是block? Block是C语言的一个语法特性,同时也是C语言的运行时特性,它很像C中的函数指针,因为你可以像使用函数指针一样的去使用block对象:它也很像C++中的 ...

  2. IOS Block代码块的定义与使用

    代码块的本质是和其他的变量类似,不同的是,代码块存储的数据是一个函数体.使用代码块,你可以像调用其他标准函数一样的调用,可以传入参数,并得到返回值.     脱字符是代码块的语法标记.下图表示代码块的 ...

  3. Block代码块中使用局部变量注意点

    第一次写代码遇到报这个错,实在是想不通为什么,按常理应该是不会有问题,报错的呀??纠结了一会之后只好仔细查看报错原因咯,原来是: 当我们在block代码块中使用局部变量时,就会很容易出现如图的错误. ...

  4. IOS学习4——block代码块

    本文转载自:iOS开发-由浅至深学习block 一.关于block 在iOS 4.0之后,block横空出世,它本身封装了一段代码并将这段代码当做变量,通过block()的方式进行回调.这不免让我们想 ...

  5. OC Block(代码块)

    #import "ViewController.h" @interface ViewController () @end @implementation ViewControlle ...

  6. java synchronized修饰普通方法,修饰静态方法,修饰代码块,修饰线程run方法 比较

    synchronized用于多线程设计,有了synchronized关键字,多线程程序的运行结果将变得可以控制.synchronized关键字用于保护共享数据. synchronized实现同步的机制 ...

  7. iOS - OC Block 代码块

    前言 Block 是一段预先准备好的代码,可以在需要的时候执行,可以当作参数传递.Block 可以作为函数参数或者函数的返回值,而其本身又可以带输入参数或返回值.Block 是 C 语言的,类似于一个 ...

  8. iOS - Block 代码块

    1.Block Block 是一段预先准备好的代码,可以在需要的时候执行,可以当作参数传递.Block 可以作为函数参数或者函数的返回值,而其本身又可以带输入参数或返回值.Block 是 C 语言的, ...

  9. 构造方法、封装、关键字(this、static)和代码块的介绍

    1.构造方法 1.1 构造方法与成员方法的区别 构造方法分为无参构造和有参构造,其中有参构造方法和无参构造方法为方法的重载关系. 构造方法在初始化一个类的对象时进行调用,它没有返回值,方法名与类名相同 ...

随机推荐

  1. Service Provider模式

    参考文章:[http://blog.csdn.net/zl3450341/article/details/7227197] Service Interface:服务接口,将服务通过抽象统一声明,供客户 ...

  2. UVa11167 Monkeys in the Emei Mountain(最大流)

    题目大概说有n只猴子,猴子们在某个时间段需要喝vi时间的水,各个单位时间段最多允许m只猴子同时喝水,问猴子们能否成功喝水并输出一个可行的方案,输出方案的时间段区间要从小到大排序并且合并连续的区间. 首 ...

  3. BZOJ4699 : 树上的最短路

    这道题主要是要解决以下两个问题: 问题1: 给定一个点$x$,如何取出所有经过它的下水道? 一条下水道经过$x$等价于它起点在$x$的子树里面且终点不在$x$的子树里面,或者两端点的lca就是$x$. ...

  4. HDU 2222 & ac自动机模板

    题意: 求n个模板串在匹配串中出现了几个. SOL: 反正就是模板啦...似乎比KMP都简单----这么说似乎有点不道德...毕竟先看的KMP而他们并没有什么不同... 貌似自己的理解和他们画的图还是 ...

  5. ACM 分数加减法

    分数加减法 时间限制:3000 ms  |  内存限制:65535 KB 难度:2   描述 编写一个C程序,实现两个分数的加减法   输入 输入包含多行数据 每行数据是一个字符串,格式是" ...

  6. Android -- EditText方法

    1. 选择需要的内容 final EditText myEditText=(EditText)findViewById(R.id.editText1); //编辑框对象 myEditText.setT ...

  7. bug:无法给图片加边框

    一,经历 1.错误代码 _avatarView.layer.cornerRadius = GIFT_AVATAR_WIDTH * 0.5; _avatarView.layer.borderColor ...

  8. 使用IE建多个会话的小技巧

    1 按F10出现菜单 2 选择文件----新建会话即可

  9. Windows Phone 8 Sync

    A lot of the below depends on the types of data, how often it is changing, and how often it is likel ...

  10. [转] 擎天哥as3教程系列第二回——性能优化

    所谓性能优化主要是让游戏loading和运行的时候不卡. 一  优化fla导出的swf的体积? 1,  在flash中,舞台上的元件最多,生成的swf越大,库里面有连接名的元件越多,swf越大.当舞台 ...