开发该选择Blocks还是Delegates(转)

原文链接:http://blog.stablekernel.com/blocks-or-delegates/

By Joe Conway,CEO | Jul 11,2013 11:29:00 AM



有人问了我一个很棒的问题,我把这个问题总结为:“开发过程中该选择 blocks or delegates?当我们需要实现回调的时候,使用哪一种方式比较合适呢?”

一般在这种情况下,我喜欢问我自己:“如果问题交给Apple,他会怎么做呢?”当然,我们都知道Apple肯定知道怎么做,因为从某一层面上看,Apple的文档就是一本用来指导我们如何使用设计模式的指导书。

因此我们需要去研究一下Apple分别是在什么情况下使用delegate和block,如果我们发现了Apple做这种选择的套路,我们就可以构建出一些规则,可以帮助在我们在自己的代码中做相同选择。

要找出Apple使用delegate的场景很简单,我们只要搜索官方文档中的“delegate”,就会获取到很多使用delegation的类。

但是搜索Apple中有关使用blocks的文档就有点困难了,因为我们不能直接搜索文档中的“^” 。然而,Apple声明方法时有很好的命名习惯(这也是我们精通iOS开发的一项必备技能)。例如:一个以NSString为参数的方法,方法的selector就会有String字眼,像initWithString;dateFromString;StartSpeaingString。

当Apple的方法使用block,这个方法将会有“Handler”,“Completion”或者简单的“Block”作为selector;因此我们可以在标准的iOS API文档中搜索这些关键词,用以构建一个可信任的block用例列表。

1.大多数delegate protocols 都拥有几个消息源。

以我正在看的GKMatch为例(A GKMatch object provides a peer-to-peer network between a group of devices that are connected to Game Center,是iOS API中用来提供一组设备连接到Game Center点对点网络的对象)。从这个类中可以看到消息的来源分别是:当从其他玩家那接收到数据、当玩家切换了状态、当发生错误或者当一个玩家应该被重新邀请。这些都是不同的事件。如果Apple在这里使用block,那么可能会有以下两种解决方式:

  • 可以对应每一个事件注册相应的block,显然这种方式是不合理的。( If someone writes a class that does this in Objective-C, they are probably an asshole.)
  • 创建一个可以接受任何可能输入的block

1

void?(^matchBlock)(GKMatchEvent?eventType,?Player?*player,?NSData?*data,?NSError?*err);

很明显这种方式既不简便又不易读,所以你可能从未看过这样的解决方案。如果你看过这样的解决方式,但是这显然是一个糟糕至极的代码行,你不会有精力去维护这个。

因此,我们可以得出一个结论:如果对象有超过一个以上不同的事件源,使用delegation。

2.一个对象只能有一个delegate

由于一个对象只能有一个delegate,而且它只能与这个delegate通信。让我们看看CLLocationManager 这个类,当发现地理位置后,location manager 只会通知一个对象(有且只有一个)。当然,如果我们需要更多的对象去知道这个更新,我们最好创建其他的location manager。

这里有的人可能想到,如果CLLocationManager是个单例呢?如果我们不能创建CLLocationManager的其他实例,就必须不断地切换delegate指针到需要地理数据的对象上(或者创建一个只有你理解的精密的广播系统)。因此,这样看起来,delegatetion在单例上没有多大意义。

关于这点,最好的印证例子就是UIAccelerometer。在早期版本的iOS中,单例的 accelerometer 实例有一个delegate,导致我们必须偶尔切换一下。这个愚蠢的问题在之后的IOS版本被修改了,现在,任意一个对象都可以访问CMMotionManager block,而不需要阻止其他的对象来接收更新。

因此,我们可以得出另一个结论:“如果一个对象是单例,不要使用delegation”。

3.一般的delegate方法会有返回值

如果你观察一些delegate方法(几乎所有的dataSource方法)都有一个返回值。这就意味着delegating对象在请求某些东西的state(对象的值,或者对象本身),而一个block则可以合理地包含state或者至少是推断state,因此block真正是对象的一个属性。

让我们思考一下一个有趣的场景,如果向一个block提问:“What do you think about Bob?”。block可能会做两件事情:发送一个消息去捕获对象并询问这个对象怎么看待Bob,或者直接返回一个捕获的值。如果返回了一个对象的响应,我们应该越过这个block直接获取这个对象。如果它返回了一个捕获的值,那么这应该是一个对象的属性。

从以上的观察,我们可以得出结论:如果对象的请求带有附加信息,更应该使用delegation

4.过程 vs 结果(Process vs. Results)

如果查看NSURLConnectionDelegate 以及 NSURLConnectionDataDelegate,我们在可以protocol中看到这样的消息:我将要做什么(如: willSendRequest,将要发送请求)、到目前为止我知道的信息(如:canAuthenticateAgainstProtectionSpace)、我已经完成这些啦( didReceiveResponse,收到请求的回复,即完成请求)。这些消息组成一个流程,而那些对流程感兴趣的delegate将会在每一步得到相应的通知。

当我们观察handler和完整的方法时,我们发现一个block包含一个响应对象和一个错误对象。显然这里没有任何有关“我在哪里,我正在做什么的”的交互。

因此我们可以这样认为,delegate的回调更多的面向过程,而block则是面向结果的。如果你需要得到一条多步进程的通知,你应该使用delegation。而当你只是希望得到你请求的信息(或者获取信息时的错误提示),你应该使用block。(如果你结合之前的3个结论,你会发现delegate可以在所有事件中维持state,而多个独立的block确不能)

从上面我们可以得出两个关键点。首先,如果你使用block去请求一个可能失败的请求,你应当只使用一个block。我们可以看到如下的代码:


1

2

3

4

5

[fetcher makeRequest:^(id result) {

   // do something with result

} error:^(NSError *err) {

    // Do something with error

}];

上面代码的可读性明显比下面block的可读性差(作者说这个是他不谦虚的观点,其实个人认为没有那么严重)


1

2

3

4

5

6

7

[fetcher makeRequest:^(id result, NSError *err) {

     if(!err) {

         // handle result

     else {

        // handle error

     }

}];

 

时间: 2024-10-13 11:16:25

开发该选择Blocks还是Delegates(转)的相关文章

开发该选择Blocks还是Delegates

前文:网络上找了很多关于delegation和block的使用场景,发现没有很满意的解释,后来无意中在stablekernel找到了这篇文章,文中作者不仅仅是给出了解决方案,更值得我们深思的是作者独特的思考和解决问题的方式,因此将这篇文章翻译过来,和诸君探讨,翻译的很多地方不是很到位,望大家提出意见建议. 有人问了我一个很棒的问题,我把这个问题总结为:“开发过程中该选择 blocks or delegates?当我们需要实现回调的时候,使用哪一种方式比较合适呢?” 一般在这种情况下,我喜欢问我自

iOS--开发该选择Blocks还是Delegates

原文链接:http://blog.stablekernel.com/blocks-or-delegates/ 有人问了我一个很棒的问题,我把这个问题总结为:“开发过程中该选择 blocks or delegates?当我们需要实现回调的时候,使用哪一种方式比较合适呢?” 一般在这种情况下,我喜欢问我自己:“如果问题交给Apple,他会怎么做呢?”当然,我们都知道Apple肯定知道怎么做,因为从某一层面上看,Apple的文档就是一本用来指导我们如何使用设计模式的指导书. 因此我们需要去研究一下Ap

开发语言选择事项

开发语言选择考虑项: 团队 成本:主要是时间成本和质量成本.为此还需要考虑人员的培养周期.学习的周期.团队配合的周期.人员流失带来的人力成本 控制:选择了这种语言能不能始终保持控制度 项目特点:根据不同项目需求,选择合适的语言 技术健壮性:包括技术是否安全.文档是否健全.活跃性,例如这种框架社区是否活跃,是否有持续性.

AES128和AES256主要区别和安全程度是多少?他们对于机器的消耗是怎样的?两者性能如何?实际开发如何选择?

高级加密标准(英语:Advanced Encryption Standard,缩写:AES),在密码学中又称Rijndael加密法,是美国联邦政府采用的一种区块加密标准.这个标准用来替代原先的DES,已经被多方分析且广为全世界所使用.经过五年的甄选流程,高级加密标准由美国国家标准与技术研究院(NIST)于2001年11月26日发布于FIPS PUB 197,并在2002年5月26日成为有效的标准.2006年,高级加密标准已然成为对称密钥加密中最流行的算法之一.    不同于它的前任标准DES,R

为什么游戏开发要选择c语言?

在学游戏开发的时候,老师总是要先学c++或者有几年c++的开发经验:当时由于是计算机语言的小白,不知道为什么,后来学了几种计算机语言后就明白了,原来c++语言开发出来的游戏,尤其是大型的游戏运行起来更有效率,为什么这么说呢?计算机上的大部分语言的底层都是c语言,也就是说他们是包装起来的c语言:这样用c语言开发出来的游戏可以直接运行,而其他的语言呢,则间接的最后还是要回归到c语言上运行,这样对于大型的游戏来说浪费了很多时间,当然这并不是说其他的语言不好,这是从一个角度去分析开发游戏选择c语言的原因

安卓开发sdk选择和兼容问题

1.minSdkVersion:8 在安装程序的时候,如果目标设备的API版本小于minSdkVersion,或者大于maxSdkVersion,程序将无法安装. 2.targetSdkVersion:19 也就是说,如果targetSdkVersion与目标设备的API版本相同时,运行效率可能会高一些.但是,这个设置仅仅是一个声明.一个通知,不会有太实质的作用,比如说,使用了targetSdkVersion这个SDK版本中的一个特性,但是这个特性在低版本中是不支持的,那么在低版本的API设备上

从事web开发,选择学习PHP还是Python呢?

PHP和Python,想要从事web开发该选择哪个呢?我想很多人都出现过这样的疑问吧,今天小编为大家简单的介绍一下. 从目前互联网发展趋势来说,当前掌握Python语言的发展空间更大一些,发展前景更好,对比PHP来说,Python可以做的事情更多. Python除了可以从事web开发之外,还可以从事大数据开发.人工智能.系统运维等领域,而且热度处于持续上升的阶段中. 如果单纯从web开发方面你来说,很多人可能会重点关注PHP语言,因为PHP语言在开发领域有着非常不错的作用,尤其是很多中小型web

iOS开发-照片选择

本来想做个注册登录的表单的,想想还是先做个简单的头像选择,一般情况下不管是内部管理系统还是面向公众的互联网公司,注册登录是免不了的,用户头像上传是免不了的,尤其是企业用户,上传了自己的图片才感觉自己买的系统是比较值的.iOS开发中上传图片还是比较简单的,通过UIImagePickerController和协议就很容易的实现的图片的选择和上传. 页面布局 首先看下视图,一个按钮,一个标签和一个ImageView: 界面很简单,头文件中声明一下UIImageView: @property (weak

工若善其器,必然利其事。 HTML5开发工具选择

本人没有美工功底,学习html5的主要目的也不是为了做网页设计, 而是学习其脚本语言javascript的编写, 还有就是CSS. 于是在网上到处找html5开发的资料,html5的开发工具等等. 网上很多朋友都推荐有好几款开发工具,我也试着下载安装过有好几款, 其中网友比较多使用的是dreamweaver, 但本人觉得Dreamweaver对于网页设计者来说应该是最佳的选择,  但由于 Dreamweaver没有调试功能,而且javascript的自动提示功能不怎么好使,作为代码编写为主的开发