iOS------Block

block object是一个C语言级别的语法和运行时特性。它与标准C函数很类似。不同之处在于block包含变量,这些变量绑定于自动的(stack)或者受管理的(heap)内存。因此block维护了一组状态,从而可以在执行过程中来影响行为。

block在OS X10.6及之后版本,iOS4.0及之后版本的GCC和Clang上是可用的。block的运行时是开源的,链接:LLVM's compiler-rt subproject repository。它也被提交给C标准工作小组作为苹果对C语言的扩展:N1370:Apple's Extensions to C

1、block的功能

block是一个匿名的内联代码集合:

1)像函数一样有类型化的参数;

2)有一个可推导的或者已声明的返回类型;

3)可以捕捉它被定义的词法范围的状态;

4)视情况的可以修改被定义词法范围的状态;

5)与同词法范围的block共享修改的潜在能力;

6)即便被定义的词法范围已经被销毁,仍能继续共享和修改这个词法范围定义的状态

block可以被复制,被传递给其它线程做推迟执行。编译器和运行时负责安排block引用的变量被一直保存着,只要block的所有拷贝依然存在。

2、block的用途

block是小的,自包含的代码片段,经常备用来封装会被并发执行的、或者针对集合类型的项目的、以及另一个操作完成的之后回调的一块工作单元。block经常作为矿机方法的参数。block允许访问本地变量,这样你就可以不用定义数据结构来包含执行一个回调操作所需的上下文信息。

3、block基本语法

1)使用^操作符来声明一个block变量,{}内包含具体定义,“;”来表示声明的结束:

int multiplier = 7;

int (^myBlock)(int) = ^(int num) {

return num * multiplier;

};

注意:block可以使用它被定义的作用域内的变量

block被定义之后,可以像使用函数一样使用:

print("%d", myBlock(3));

声明block变量像声明函数指针一样,下面是一些合法的声明:

void (^blockReturningVoidWithVoidArgument)(void);

int (^blockReturningIntWithIntAndCharArguments)(int, char);

void (^arrayOfTenBlocksReturningVoidWithIntArgument[10])(int);

block也支持可变参数(...),没有参数的block必须在参数列表指定void。你可以转换block引用为任意类型的指针,反之亦然,但是block引用的指针不能用*来解引用。因此block的大小不能再编译的时候计算到。

2)、可以不声明block变量,直接把它作为一个函数参数内联的使用:

[presentingVC presentViewController:presentedVC animated:YES completion:^{

printf("present finished");

}];

3)定义一个block类型:

typedef float (^MyBlockType)(float, float);

MyBlockType myFirstBlock = //...;

MyBlockType mySecondBlock = ^(float a, float b) {

        return a - b;

}

4、block和变量

block对象定义体代码中,变量以5种方式对待的,你可以像函数一样引用3种标准类型的变量:

1)全局变量,包括static本地变量

2)全局函数

3)封闭作用于的本地变量和参数

4)在函数级别的__block变量。这一类在block内是可变的,并且如果引用的block被拷贝到heap中时,这一类变量会被保存

5)const

在一个block中有以下规则被应用于变量上:

1)全局变量是可访问的,包括存在于封闭词法范围的static变量

2)传递进block的参数是可访问的

3)词法范围内的栈(stack,非static)本地变量被捕捉为const变量,它们的值在程序中的block表达式的时刻被拿到。嵌套的block中,从最近的词法范围捕捉值。

4)词法范围内声明的__block存储修饰符的本地变量通过引用提供的,所以是可变的

5)block内声明的本地变量跟一般函数内本地变量一样。每一次block的调用为本地变量提供新的值。对于内嵌的block,这些变量又是被看做const或者通过引用来使用的变量

例:本地非静态变量

int x = 123;

void (^printXAndY)(int) = ^(int y) {

//x = x + 1;  如果放开注释,Error

printf("%d %d\n", x, y);

};

printXAndY(456); // prints: 123 456

5、__block存储类型。

__block修饰符是的block中导入的变量是可变的,即就是read & write,它类似于本地变量的register,auto,static存储类型。__block变量对于声明该变量的此法范围和所有的block和同一词法范围声明的或者创建的block拷贝。所以只要引用__block变量的block存在,即便是栈结构销毁,__block变量依然得以幸存。

作为优化,block存储一开始在stack上,就和block一样。但是一旦block被拷贝,例如使用Block_copy(OC中发送一个copy),变量才会被拷贝到heap上。所以__block变量的地址随时间可能会变。

__block变量有两个限制:1)不能是可变长度数组 2)不能是C99中包含可变长度数组的结构体

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'

}

6、对象和block变量

当block被拷贝,block内部使用的对象变量会被强引用。所以:

1)如果你通过引用来访问一个实例变量,self被强引用

2)如果你通过值来访问一个实例变量,这个变量被强引用

dispatch_async(queue, ^{

// instanceVariable is used by reference, a strong reference is made to self

doSomethingWithObject(instanceVariable);

});

id localVariable = instanceVariable;

dispatch_async(queue, ^{

/*

localVariable is used by value, a strong reference is made to localVariable

(and not to self).

*/

doSomethingWithObject(localVariable);

});

7、拷贝block

一般,不需要拷贝一个block,只有在你想当声明block的作用于被销毁之后继续使用这个block才需要拷贝它,拷贝会把block移到heap中:

Block_copy();
Block_release();

这两个必须成对出现的,以防止内存泄漏

8、调试

设置断点,单步调试。可以在GDB会话使用invoke-block:

$ invoke-block myBlock 10 20     //对应block名和参数。

传C字符串有些特殊,要进行转义

$ invoke-block doSomethingWithString "\"this string\"'


本文内容基本是苹果文档Blocks Programming Topics翻译。基本上的知识点应该都知道的。好闲啊!!!

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

推荐阅读更多精彩内容

  • 《Objective-C高级编程》这本书就讲了三个东西:自动引用计数、block、GCD,偏向于从原理上对这些内容...
    WeiHing阅读 9,804评论 10 69
  • 前言 Blocks是C语言的扩充功能,而Apple 在OS X Snow Leopard 和 iOS 4中引入了这...
    小人不才阅读 3,759评论 0 23
  • 目录 Block概述 Block定义方式 Block保存代码 Block传值 Block对外部变量的传递 Bloc...
    子斌阅读 1,389评论 2 7
  • Block是iOS在4.0之后新增的程式语法,严格来说block的概念并不算是基础程式设计的范围,对初学者来说也不...
    Bager阅读 899评论 0 0
  • 《Objective-C高级编程》是一本有趣又难懂的书,全书就讲了引用计数、Block、GCD三个概念,有趣是因为...
    kamous阅读 55,212评论 22 206