iOS 使用位段为你的协议实现缓存功能

在设计接口的时候,委托是常用的交互方式,一般的,我们在使用协议时会写出以下代码。

if ([delegate respondsToSelector:@selector(someMothod:)]) {
        [delegate someMothod:(id)sender];
    }

一般情况下没有问题,事实上,以上代码可以满足大部分的需求,但是假设你所实现的协议方法是一个类似网络下载进度回调的功能,每隔很短的小段时间就需要回调一次呢?

你会发现,除了第一次检测委托对象是否响应某个选择子有意义外,之后的检测都是多余的。如果委托对象本身没变,那么不大可能会忽然不能响应某个选择子。鉴于此,我们可以把委托对象能否响应某个协议方法这一信息缓存起来,已优化程序效率。

假设现在有一个进度回调的协议方法

- (void)networkDidUpdateProgressTo:(float)progerss;

以上方法由于需要监听进度,需要频繁地回调progress参数,如果能够缓存委托对象能否响应的信息,我们就不必每次都去执行以下函数

if ([delegate respondsToSelector:@selector(someMothod:)])

将方法相应能力缓存起来的最佳途径就是使用C语言的“位段”数据类型。

这里简单介绍一下位段:
什么是位段呢? 位段是 C 语言特有的数据结构, 它允许我们定义一个由位组成的段, 并可为它赋以一个名字。
二进制位是数据的基本单位,它比字节还小,一个字节由 8 位组成, 而在某些计算机系统中则可能是 16 位。
事实上,如果需要标志一个信息,一位就足够了,但是由于字节是存储的最小单位,所以所有的变量至少要使用一个字节(比如BOOL值)。
如果我们想在一个很大的表中存储很多标志, 那么 "被浪费" 的内存空间是很可观的。幸运的是,在 C 语言中, 我们可以使用叫做位段的构造类型来定义一个结构体,从而定义某个字段所用的二进制位个数为某个特定的值。

struct data{                           //包含位段的结构体
    unsigned int fieldA : 8;    //位段fieldA,占8二进制位
    unsigned int fieldB : 4;    //位段fieldB,占4二进制位
    unsigned int fieldC : 2;    //位段fieldC,占2二进制位
    unsigned int fieldD : 1;    //位段fieldD,占1二进制位
}
//位段列表的形式为: 类型说明符 位域名:位域长度

以上结构体中,fieldA 位段将占用 8 个二进制位,fieldB 则为 4个,以此类推。于是,fieldA 可以表示 0 至 255 之间的值,而fieldD可以表示 0 或 1 这两个值。

我们可以像 fieldD 这样,把委托对象是否实现了协议中的相关方法这一信息缓存起来。如果创建的结构体中只有大小为 1 的位段,那么就能把很多 Boolean 值塞入一小块数据里面了(原来存一个BOOL值的空间,现在能存8个),我们现在文件中声明一个结构体。

struct {
    unsigned int delegateMothod1 : 1;
    unsigned int delegateMothod2 : 1;
    unsigned int delegateMothod3 : 1;
}  _delegateFlags;

然后重写我们的delegate的setter方法:

-(void)setDelegate:(id<personalDelegate>)delegate
{
    _delegate=delegate;
    _delegateFlags.delegateMothod1=[delegate respondsToSelector:@selector(delegateMothod1:)];
    _delegateFlags.delegateMothod2=[delegate respondsToSelector:@selector(delegateMothod2:)];
    _delegateFlags.delegateMothod3=[delegate respondsToSelector:@selector(delegateMothod3:)];
}

现在委托对象如果能够相应协议方法,位段就可以将其以一位的大小缓存起来,然后我们在之后调用委托对象的相关方法时,就不用检测委托对象是否能响应给定的选择子了,而是直接查询结构体里的标志:

if (_delegateFlags._delegateFlags.delegateMothod1){
    [_delegate delegateMothod1:];
}

在相关方法要调用很多次的时候,值得进行这种优化,而是否需要优化,则应依照具体代码来定。这需要分析代码性能,并找出瓶颈,若发现执行速度需要改进,则可使用此技巧。如果要频繁通过数据源协议从数据源中获取多分相互独立的数据,那么这项优化技术极有可能会提高程序效率。

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

推荐阅读更多精彩内容

  • 国家电网公司企业标准(Q/GDW)- 面向对象的用电信息数据交换协议 - 报批稿:20170802 前言: 排版 ...
    庭说阅读 10,800评论 6 13
  • *面试心声:其实这些题本人都没怎么背,但是在上海 两周半 面了大约10家 收到差不多3个offer,总结起来就是把...
    Dove_iOS阅读 27,107评论 29 470
  • 从三月份找实习到现在,面了一些公司,挂了不少,但最终还是拿到小米、百度、阿里、京东、新浪、CVTE、乐视家的研发岗...
    时芥蓝阅读 42,137评论 11 349
  • 1. Java基础部分 基础部分的顺序:基本语法,类相关的语法,内部类的语法,继承相关的语法,异常的语法,线程的语...
    子非鱼_t_阅读 31,497评论 18 399
  • 早上经彭老师确认没有下雨,我蹬上运动鞋,背上小包包,准备步行上班,到了楼下一看,明明淅淅沥沥下着雨,赶紧跑上楼...
    瘪瘪元子阅读 247评论 1 3