Block的嵌套使用

作者: KFAaron | 来源:发表于2016-05-18 16:04 被阅读3457次

前言

唐巧的技术博客里面有篇谈Objective-C Block的实现的文章,对于block的内部数据结构、三种类型以及相关的内存管理方式说的比较详细,关于这些内容我就不在这画蛇添足了,我主要要说的是block的嵌套使用。在说这个之前,推荐大家一个有意思的Objective-C Blocks Quiz,也许做完这五个小题目,你对自己掌握block的程度会有一个更客观的认识。

block为什么嵌套

用过WebViewJavascriptBridge进行Objective-C和JS的交互的朋友对于下面这段代码肯定特别熟悉:

[WebViewJavascriptBridge bridgeForWebView:webView handler:^(id data, WVJBResponseCallback responseCallback) {
    NSLog(@"Received message from javascript: %@", data);
    if (responseCallback) {
        responseCallback(@"Right back atcha");
    }
}]

如果WVJBResponseCallback换成任何一个咱们熟悉的类,那么这种模式就是咱们再熟悉不过的一种回调方法,但是通过看源文件,如下:

typedef void (^WVJBResponseCallback)(id responseData);
typedef void (^WVJBHandler)(id data, WVJBResponseCallback responseCallback);

可以看出WVJBResponseCallback也是一个block,第一个参数data,咱们很容易理解,传值方式的一种,可是第二个参数是一个block,是不是感觉不太常见呢?别着急,这就是我今天要讲的。

讲之前咱们先思考一个问题。假设有两个类,类A和类B。类A要让类B干一些事,类B干完之后得反馈给类A,类A收到类B的反馈信息之后需要进行一些处理,然后还得再反馈一些信息给类B,类B收到类A的反馈信息之后还要进行一些处理。

碰到这个问题,你会怎么处理呢?代理、通知等等,要实现这个问题都不难,但是个人认为用的最舒服的还是block。用block嵌套解决这个问题,就显得尤为简单。

block怎么嵌套

为了显示这个问题,我们先建一个KFABlockTestB类,在KFABlockTestB.h先定义两个block,如下:

typedef void(^Ablock)(id testData);
typedef void(^Bblock)(id data, Ablock testBlock);

然后给这个类添加一个Bblock的属性,并添加一个实例方法,如下:

@interface KFABlockTestB : NSObject

@property (nonatomic, copy) Bblock byBlock;

- (void)testActionWith:(Bblock)block;

@end

然后在KFABlockTestB.m文件里实现这个方法:

- (void)testActionWith:(Bblock)block
{
    _byBlock = block;
    
    NSString *striData = @"BlockTestB say hello to VC";
    _byBlock(striData, ^(id testData){
        NSLog(@"BlockTestB get response from VC: %@",testData);
    });
}

在这里,striData就是我要反馈回去的信息,那个打印动作就是受到调用这个方法所在的类再次返回回来信息时进行的处理动作。然后在ViewController里引入KFABlockTestB.h,并定义一个属性,如下:

#import "ViewController.h"
#import "KFABlockTestB.h"

@interface ViewController ()

@property KFABlockTestB *blockTestB;

@end

在viewDidLoad里对blockTestB进行初始化,并调用KFABlockTestB的实例方法testActionWith:,并在回调方法block里对传入的值进行打印,如下:

_blockTestB = [KFABlockTestB new];
    
[_blockTestB testActionWith:^(id data, Ablock testBlock) {
   NSLog(@"Get message from blockTestB: %@",data);
   if (testBlock) {
       testBlock(@"Response for message from VC");
   }
}];

通过运行,我们会发现控制台输出结果如下:

2015-12-17 02:17:27.518 KFABlockDemo[40010:2703474] Get message from blockTestB: BlockTestB say hello to VC
2015-12-17 02:17:27.518 KFABlockDemo[40010:2703474] BlockTestB get response from VC: Response for message from VC

这是为啥呢?因为block实际上是一个对象,通过看它的内部结果,我们发现它也有isa指针,所以block本身也可以作为一个参数进行传值。在这个demo里,KFABlockTestB在执行testActionWith:这个方法的时候,通过回调方法相当于进行了一次两个数据的传值。一个是

data = @"BlockTestB say hello to VC"

一个是

testBlock = ^(id testData){
        NSLog(@"BlockTestB get response from VC: %@",testData);
    })

这样再去看viewController在block回调里的动作和控制台的输出结果就一目了然了。

总结

block说难并不难,现在相关的资料很多,只要我们静下心来好好看看它的实现原理,并多加练习,就会比较熟练。但是block也没有咱们想的那么简单,比如作为属性时的修饰词、传值的内存管理等等,得多下功夫、多费心才能真正掌握。如果还有其他问题或者建议,请通过微博或者邮件联系我,也可以直接在评论区提出。

本文原创,如果喜欢或者对你有用,在转载和引用时请标明出处。

参考链接

相关文章

  • Block的嵌套使用

    前言 唐巧的技术博客里面有篇谈Objective-C Block的实现的文章,对于block的内部数据结构、三种类...

  • Block使用场景

    引言 最近在研究RAC的时候,发现绝大部分代码实现如下所示: 可以发现是block嵌套使用,这是使用block实现...

  • #iOS Dev.#UITableView

    关于UITableViewCell嵌套UITextField控件时 重用数据处理 使用Block回调TextFie...

  • HTML 常用的标签

    iframe标签 :用于嵌套页面,name属性可以与a标签关联使用 a标签:target="_block"打开新页...

  • iOS 之 block(4.4)

    本章主题,讨论 block 的嵌套 总结:可以看出block 被捕获,有 BLOCK_FIELD_IS_BLOCK...

  • 嵌套block的应用(数据互传、响应式编程、链式编程)

    前言 什么是嵌套block?为了防止误解,先上代码 本文所说的嵌套block是指,像Block1那样,参数中有bl...

  • iOS block嵌套block中weakify的使用

    结论:嵌套中的block只需要写strongify,不需要再写一次weakify 只要持有block的变量和blo...

  • Block的嵌套

    有人喜欢协议,有人喜欢Block,但是根据需求要嵌套Block,即Block里面有Block.我百度了好想没有我想...

  • 易忽略的循环引用

    1、嵌套循环引用 解决方案: 注意:建议嵌套Block时,block内部新声明一个方法,从而不会显得@weakif...

  • 微信小程序 【开发】 自学总结 2

    减少逻辑判断嵌套,而逐层增加的view标签,可以使用block,来挂载条件判断如: 频繁切换显示消失的标签,使用h...

网友评论

本文标题:Block的嵌套使用

本文链接:https://www.haomeiwen.com/subject/kkewrttx.html