开发时Blocks跟Delegates如何选择----董鑫
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如何选择----董鑫的更多相关文章
- 键盘弹起及lab时的动态计算高度 --董鑫
1.键盘抬起或掉下时,动态计算高度 2.动态计算Label的高度 计算的高度时,numberOfLines必须设置为0: 2.1 ios7.0之后 2.2 iOS 7.0之前
- 开发该选择Blocks还是Delegates
前文:网络上找了很多关于delegation和block的使用场景,发现没有很满意的解释,后来无意中在stablekernel找到了这篇文章,文中作者不仅仅是给出了解决方案,更值得我们深思的是作者独特 ...
- 开发该选择Blocks还是Delegates(转)
原文链接:http://blog.stablekernel.com/blocks-or-delegates/ By Joe Conway,CEO | Jul 11,2013 11:29:00 AM 有 ...
- iOS 开发该选择Blocks还是Delegates
http://www.cocoachina.com/ios/20150925/13525.html 前文:网络上找了很多关于delegation和block的使用场景,发现没有很满意的解释,后来无意中 ...
- WCF开发时如何选择正确的实例模式(InstanceMode)?
WCF开发时如何选择正确的实例模式(InstanceMode)? 在使用WCF实例模型时,你是否思考过这几个的问题: ”WCF中的实例模式如何正确应用”? ”使用WCF中的实例模式有何原则可以遵循 ...
- C++开发时字符编码的选择
最近看了很多有关字符编码的讨论帖子, 自己也做了很多尝试, 针对linux和windows上字符编码的选择做了个简单整理, 在此做个记录 首先是基础编码知识, 下面我列出的4个编码方式或字符集是我们应 ...
- Golang Web开发时前端出现谜之空白换行的坑
在使用Golang做Web开发时,有时候渲染出来的模板在前台显示时会出现一些奇怪的空白换行,具体特征就是查看css样式表并没有相关定义的空白部分. 分析: 查看出现问题页面的网页源代码,复制空白换行部 ...
- J2EE开发时的包命名规则
http://www.blogjava.net/paulwong/archive/2012/04/15/374675.html 转一个J2EE开发时的包命名规则,养成良好的开发习惯 代码编写规范目的: ...
- iOS开发时,在Xcode中添加多个Targets进行版本控制
在iOS开发中,很可能有以下场景:需要开发多个版本,或因需区分收费版,免费版,或因为网络环境需要区分测试版,发布版,或因渠道不同需要区分企业版,AppStore版等等.解决办法无非就是CheckOut ...
随机推荐
- Linux查找class类所在jar包
1.说明 写代码或者定位问题的时候, 经常发生只知道类名不知道其所在jar包的问题, 在Eclipse中可以使用Ctrl+Shift+T查找类, 但是如果类所在的jar包不在Build Path中, ...
- 开源社区合入patch的步骤
以Ranger项目为例,说明开源社区合入patch的详细步骤. 1.reviews页面下载patch 进入到review页面:https://reviews.apache.org/r/67919/ 点 ...
- python 安装包时提示“unsupport command install”
为什么提示找不到? 电脑安装了LoadRunnder,LoadRunner也有pip.exe,导致找不到python的exe 解决方法: 切换到python pip的路径进行安装,进到这个路径下,进行 ...
- Pytest_Hook函数pytest_addoption(parser):定义自己的命令行参数(14-1)
考虑场景: 我们的自动化用例需要支持在不同测试环境运行,有时候在dev环境运行,有时候在test环境运行: 有时候需要根据某个参数不同的参数值,执行不同的业务逻辑: 上面的场景我们都可以通过" ...
- Itellij Idea使用
图片如果损坏,点击链接查看 https://www.toutiao.com/i6491635946176381454/ 创建Maven项目 JDK环境 目前大多数IDE都没有集成JDK环境,IDEA也 ...
- Flink 非对齐Unaligned的checkpoint(源码分析)
本文源码基于flink1.14 在帮助用户排查任务的时候,经常会发现部分task处理的慢,在Exactly once语义时需要等待快照的对齐而白白柱塞的情况 在flink1.11版本引入了非对齐的ch ...
- 曼孚科技:“四管齐下”筑牢AI数据隐私安全防线
谈及数据,绕不开的一个话题就是数据隐私与数据安全.随着数字化进程加快,数据安全事件频发,据Risk Based Security统计,去年国际数据泄露事件近5000起,被泄露数据近41亿条,数据造成的 ...
- 5.12-jsp分页功能学习
1.分页功能相关资料查询 分页须知知识点: (1)JDBC2.0的可滚动结果集. (2)HTTP GET请求. 一.可滚动结果集 Connection con = DriverManager.g ...
- Cesium源码剖析---Clipping Plane
之前就一直有写博客的想法,别人也建议写一写,但一直没有动手写,自己想了一下原因,就一个字:懒.懒.懒.为了改掉这个毛病,决定从今天开始写博客了,一方面对自己掌握的知识做一个梳理,另一方面和大家做一个交 ...
- 简述BIO/NIO/AIO前世今生
如下程序是简单实现了一个极其简单的WEB服务器,用来监听某个端口,接受客户端输入输出信息. 但这个程序有一个致命的问题就是连接会长时间阻塞 于是BIO版本出现了,改成了 一个连接 一个线程来处理请求 ...