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

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。我们可以看到如下的代码:

[fetcher makeRequest:^(id result) {
// do something with result
} error:^(NSError *err) {
// Do something with error
}];

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

[fetcher makeRequest:^(id result, NSError *err) {
if(!err) {
// handle result
} else {
// handle error
}
}];

开发时Blocks跟Delegates如何选择----董鑫的更多相关文章

  1. 键盘弹起及lab时的动态计算高度 --董鑫

    1.键盘抬起或掉下时,动态计算高度 2.动态计算Label的高度 计算的高度时,numberOfLines必须设置为0: 2.1  ios7.0之后 2.2 iOS 7.0之前

  2. 开发该选择Blocks还是Delegates

    前文:网络上找了很多关于delegation和block的使用场景,发现没有很满意的解释,后来无意中在stablekernel找到了这篇文章,文中作者不仅仅是给出了解决方案,更值得我们深思的是作者独特 ...

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

    原文链接:http://blog.stablekernel.com/blocks-or-delegates/ By Joe Conway,CEO | Jul 11,2013 11:29:00 AM 有 ...

  4. iOS 开发该选择Blocks还是Delegates

    http://www.cocoachina.com/ios/20150925/13525.html 前文:网络上找了很多关于delegation和block的使用场景,发现没有很满意的解释,后来无意中 ...

  5. WCF开发时如何选择正确的实例模式(InstanceMode)?

    WCF开发时如何选择正确的实例模式(InstanceMode)?   在使用WCF实例模型时,你是否思考过这几个的问题: ”WCF中的实例模式如何正确应用”? ”使用WCF中的实例模式有何原则可以遵循 ...

  6. C++开发时字符编码的选择

    最近看了很多有关字符编码的讨论帖子, 自己也做了很多尝试, 针对linux和windows上字符编码的选择做了个简单整理, 在此做个记录 首先是基础编码知识, 下面我列出的4个编码方式或字符集是我们应 ...

  7. Golang Web开发时前端出现谜之空白换行的坑

    在使用Golang做Web开发时,有时候渲染出来的模板在前台显示时会出现一些奇怪的空白换行,具体特征就是查看css样式表并没有相关定义的空白部分. 分析: 查看出现问题页面的网页源代码,复制空白换行部 ...

  8. J2EE开发时的包命名规则

    http://www.blogjava.net/paulwong/archive/2012/04/15/374675.html 转一个J2EE开发时的包命名规则,养成良好的开发习惯 代码编写规范目的: ...

  9. iOS开发时,在Xcode中添加多个Targets进行版本控制

    在iOS开发中,很可能有以下场景:需要开发多个版本,或因需区分收费版,免费版,或因为网络环境需要区分测试版,发布版,或因渠道不同需要区分企业版,AppStore版等等.解决办法无非就是CheckOut ...

随机推荐

  1. JavaScript交互式网页设计 • 【第4章 JavaScript文档对象模型】

    全部章节   >>>> 本章目录 4.1 文档对象模型简介及属性 4.1.1 文档对象模型概述 4.1.3 实践练习 4.2 document 对象查找 HTML 元素 4.2 ...

  2. 引用element-ui的Drawer抽屉组件报错问题

    前提:vue项目采取按需引入的方式引入element,并且使用其他组件都正常,没有发生异常 问题表现: 在vue项目中引用了Drawer 抽屉组件,结果报错 意思就是组件未注册,当时我的表情: 没办法 ...

  3. FastAPI快速查阅

    官方文档主要侧重点是循序渐进地学习FastAPI, 不利于有其他框架使用经验的人快速查阅 故本文与官方文档不一样, 并补充了一些官方文档没有的内容 安装 包括安装uvicorn $pip instal ...

  4. Lomsat gelral

    题目描述 You are given a rooted tree with root in vertex 11 . Each vertex is coloured in some colour. Le ...

  5. monkey介绍及常用命令

    前置准备: adb:用来连接安卓手机和PC端的桥梁,要有adb作为两者之间的维系,才能在电脑对手机进行全面的操作.(adb push 文件路径 到手机路径  adb pull 从手机拉取到电脑) mo ...

  6. unittest_expectedFailure预期用例失败(5)

    在断言用例执行结果时,会出现预期结果与实际结果不一致的情况,此时我们明确知道用例执行结果为FAIL,不想看到打印错误信息怎么办? 使用装饰器@unittest.expectedFailure标记该用例 ...

  7. 小程序canvas绘制纯色圆角区域 setdata数组某一项

    小程序canvas绘制纯色圆角区域: //方法: roundRectPath:function(ctx, x, y, w, h, r) { ctx.beginPath(); ctx.moveTo(x ...

  8. test_5 排序‘+’、‘-’

    题目是:有一组"+"和"-"符号,要求将"+"排到左边,"-"排到右边,写出具体的实现方法. 方法一: l=['-', ...

  9. Ubuntu16桌面版编译和安装OpenCV4

    欢迎访问我的GitHub https://github.com/zq2599/blog_demos 内容:所有原创文章分类汇总及配套源码,涉及Java.Docker.Kubernetes.DevOPS ...

  10. RHCSA 第六天

    一.  创建下列用户.组和组成员资格: 1.创建名为 sysmgrs 的组 2.创建用户 natasha 同时指定sysmgrs作为natasha的附加组 3.创建用户 harry 同时指定 sysm ...