使用Blocks来进行工作(二)

Blocks能够从封闭的空间中拿到值

除了包含可执行的代码,一个block同样有能力区捕捉到封闭空间内的状态。打个比方说如果你将block的申明显示在一个方法里面,在这个封闭的方法内部获得任何值可能就成了一件很容易的事情,像下面这样:

-(void)testMethod {
       int anInteger = 42;

        void (^testBlock)(void) = ^{
                NSLog("@Integer is:%i",anInteger);
        };
        testBlock();
}

在这个例子中,anInteger是一个申明在block外部的变量,但是这个变量的值却可以在block被定义了之后在其内部被捕捉到。这个变量的值只能是被捕捉到的那个值,即便你有其他具体的说明或修改,它还是当时你捉到的那个变量值!这个意味着如果你想改变这个外部变量的值在你定义block和实现这个block这段时间之内,像下面这样:

int anInteger = 42;
void (^testBlock)(void) = ^{
        NSLog(@"Integer is:%i",anInteger);
};
anInteger = 84;
testBlock();

通过上述例子我们可以发现,这个变量的值在block中并没有被影响到,这个意味着日志的输出始终会显示:

Integer is :42

这个同样也说明了block是无法更改原始变量的值,或者甚至是被捕捉到的值(这个被捕捉到的变量值对于block来说就是一个const的变量)

note:你可以尝试在block内部去修改变量值,你发现会报错;
另外,在block定义之前你去改变变量的值是可以的,block定义之后被捕捉到的话,这个值的外部变化对它是没有任何影响的。

利用__block变量来共享内存

如果你有这个需要在block内部将捕捉到的变量值进行修改的需求,你可以通过使用存储类型修饰符__block来修饰原始变量。这个意味着变量生活的内存被分享在原始变量的词汇范围和任何有block声明的范围之间。
举个例子来说,你可能会像这样重写前面提到的例子:

__block int anInteger = 42;

void (^testBlock) (void) = ^{
        NSLog(@"Integer is :%i",anInteger);
};
anInteger = 84;
testBlock();

因为anInteger被申明成一个__block变量,所以它的存储和block申明共享。这也意味着日志的输出将会变成下面这个样子:

Integer is :84

它同样也意味着block可以改变原始变量的值,像下面这样:

__block int anInteger = 42;
void(^testBlock)(void) = ^{
        NSLog("@Integer is :%i",anInteger);
        anInteger = 100;
};
testBlock();
NSLog(@"Value of original variable is now:%i",anInteger);

这一次,日志的输出将会显示:

Integer is :42
Value of original variable is now:100

你可以将Blocks作为方法或函数的参数传递

本章节前面讲的每一个例子都是blocks直接在被定义了之后进行调用。在实际中,blocks作为方法或函数调用中的参数传递也是随处可见。例如,你可能会通过线程:Grand Central Dispatch 在后台调用block,或者去定义一个block去代表重复调用的任务,就比如说当枚举一个集合的时候。

blocks同样被用来作为回调,定义任务完成时要执行的代码。例如,你的app可能现在需要通过创建一个复杂的任务对象去响应一个用户类似请求web网络服务的动作。

这个很有可能通过使用代理来完成:你可能需要去创建一个合适的代理协议,实现被要求使用到的方法,设置这个任务的代理对象,然后等待一旦这个任务结束你创建的代理对象去调用代理方法。

然而,Blocks可以让这些变得更简单,因为你可以定义一个回调行为在你初始化这个任务的时候,像下面这样:

-(IBAction)fetchRemoteInformation:(id)sender {
        [self showProgressIndicator];

        XYZWebTask *task = ....
        
        [task beginTaskWithCallbackBlock:^{
                 [self hideProgressIndicator];
        }];
}

这个例子中,调用了一个方法去显示进度指示器,然后创建并开启一个任务。告诉回调的block在指定任务完成之后要实现的代码。在这个例子中,调用一个方法去隐藏进度指示器看起来是很简单的。但是请注意,block在回调的时候,为了调用hideProgressIndicator方法需要去捕捉self对象。很重要的一点事在捕捉self对象的时候要格外小心。因为我们很容易就会创建一个循环的强引用。这个在之后的介绍中我们会提到。

在代码可读性方面,这个blocks使得我们可以在一个地方就能很容易的看到任务发生的开始和结束,避免了我们需要去追踪代理方法来寻找出任务是怎么发生的。
声明beginTaskWithCallbackBlock:方法可以像下面这个例子一样:

-(void)beginTaskWithCallbackBack:(void(^)(void))callbackBlock;

(void(^)void))说明这个参数是一个没有任何变量或返回值的block,实现方法可以通过一个很常规的途径来调用这个block,像下面这样:

-(void)beginTaskWithCallbackBlock:(void(^)(void))callbackBlock {
        ...
        callbackBlock();
}

使用一个或多个参数的block方法函数也是同样的方式:

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

推荐阅读更多精彩内容

  • Blocks编程要点 目录 简介............................................
    xuejunjun阅读 1,190评论 0 5
  • 《Objective-C高级编程》这本书就讲了三个东西:自动引用计数、block、GCD,偏向于从原理上对这些内容...
    WeiHing阅读 9,785评论 10 69
  • 在编程领域里,一个牛逼程序员和一个二逼程序员之间的区别主要是其对所用编程语言优秀特性的运用方式。要说到Object...
    Jimmy_L_Wang阅读 457评论 0 1
  • *面试心声:其实这些题本人都没怎么背,但是在上海 两周半 面了大约10家 收到差不多3个offer,总结起来就是把...
    Dove_iOS阅读 27,112评论 29 470
  • 昨天已是曾经 回不过去的旧时光 幻化成记忆沉淀 你是否有过这样的感触? 曾经多喜欢的人 如今再回首 你会笑笑不语 ...
    洛铁花开阅读 244评论 0 3