Block

title: Block
date: 2016-03-29 19:23:19
categories: iOS
tags: Block


作者:秋儿(lvruifei@foxmail.com

Blocks:

C 语言的扩充功能。带有自动变量(局部变量)的匿名函数。

匿名函数:不带名称的函数。C 语言的标准不允许存在这样的函数,但可以使用函数的指针来代替直接调用函数。

Blocks 中将该匿名函数部分称为 “Block Literal”,简称 “BlocK”。

“带有自动变量的匿名函数” 这一概念并不仅指 Blocks ,在计算机科学中,也称为闭包(Closure)、lambda 计算(lambda calculus)等。

程序语言 Block 的名称
C + Blocks Block
Smalltalk BlocK
Ruby Block
LISP Lambda
Python Lambda
C++ 11 Lambda
Javascript Anonymous function

Block 语法:

与 C 语言函数 定义相比有两点不同:

  • 没有函数名
  • 带有 “^”, 插入记号,便于查找
    ^ void (int event) {
        printf("buttonId:%d event=%d\n",i,event);
    }


Block 语法的 BN范式:

Block_literal_expression :: = ^ block_decl compound_statement_body
block_decl ::=
block_decl ::= parameter_list
block_decl ::= type_expression

^ 返回值类型 参数列表 表达式

^init (init count){ return count +1;}

Block 语法可省略的几个项目:

  • 返回值:如果表达式中有 return 语句,就使用该返回值的类型,拖过没有 return 则使用 void 类型。

      ^(int count){return count + 1;}// 返回 int 型返回值 
    
  • 参数列表:

      ^void (void){printf("Blocks\n");}
      ^{printf("Blocks\n");}// 与上面代码等价
    

Block 类型变量:

C 语言函数,将所定义函数的地址赋值给函数指针类型变量中。

int func (ini count) {
    return count + 1;
}
int (* funcptr)(int) = &func;

Block 类型变量示例:

int (^blk)(init);

对比可知:声明 Block 类型变量仅仅是将声明函数指针类型变量 的 * 变为 ^

Block 语法将 Block 赋值为Block 类型变量

int (^blk)(int) = ^(ini count){
    return count +1;
} 

int (^blk1)(int) = blk;
int (^blk2)(int);
blk2 = blk1;

// 将 Block 作为参数
void func(int (^blk)(init)){}

// 将 Block 作为返回值
int (^func()(int)) {
    return ^(int count){
        return count + 1;
    }
}

使用 typedef 来解决 函数参数和返回值中使用Block 类型变量太复杂的问题。

typedef int (^blk_t)(int);

void func(blk_t blk) {}

blk_t func() {}

调用函数的方法与使用函数指针变量调用函数的方法相同:

int result = (*funcptr)(10);

int result = blk(10);

指向 Block 类型变量的指针,即 Block 的指针类型变量

typedef int (^blk_t)(int);
blk_t blk = ^(int count){ return count +1;};
blk_t *blkptr = &blk ;
(*blkptr)(10);

截获自动变量值:

int main(){
    int dmy = 256;
    int val = 10;
    const char *fmt = "val = %d\n";
    void (^blk)(void) = ^{printf(fmt,val);};
    
    val = 2;
    fmt ="These values were changed. val = %d\n";
    
    blk();// val = 10;
    return 0;
}

__block 说明符:

若想在 Block 语法表达式中将 Block 语法外声明的自动变量的值进行改写,则该自动变量需加上 __block 说明符。

__block int val = 0;
void (^blk)(void) =^{ val = 1};
blk();
// val = 1;

截获的自动变量:

不加 __block 说明符,使用截获的自动变量不会出错,但赋值给截获的自动变量会编译错误:

id array = [[NSMutableArray alloc] init];
void (^blk)(void) = ^{
    id obj = [[NSObject alloc] init];
    [array addObject:obj]; // 不会出错
    array = [[NSMutableArray alloc] init]; // 编译错误, 需在外面的array 声明的地方添加 __block 说明符
    
}

在使用 C 语言数组时必须小心使用其指针,在 Blocks 中,截获自动变量的方法并没有实现对 C 语言数组的截获,应使用指针解决。

// 不正确
const char text[] = "hello";
void (^blk)(void) = ^{
    printf("%c\n",text[2]);
};

// 正确
const char *text[] = "hello";
void (^blk)(void) = ^{
    printf("%c\n",text[2]);
};

Blocks 的实现:

Block 实际上是作为极普通的 C 语言源代码来处理的。通过支持 Block 的编译器,含有 Block 语法的源代码转换为一般的 C 语言编译器能够处理的源代码,然后被编译。

将含有 Block 语法的源代码变换为 C++ 的源代码。仅使用了 struct 结构, 本质是 C 语言源代码。

clang -rewrite-objc 源代码文件名

各种实现方式,现在无法理解,之后再补。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,189评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,577评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,857评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,703评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,705评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,620评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,995评论 3 396
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,656评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,898评论 1 298
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,639评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,720评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,395评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,982评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,953评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,195评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,907评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,472评论 2 342

推荐阅读更多精彩内容