博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
iOS委托模式优化
阅读量:6215 次
发布时间:2019-06-21

本文共 2385 字,大约阅读时间需要 7 分钟。

        前言:在实现代理模式时,如果协议中的方法是可选的,那么就会写出一大批类似于这样的代码:

if ([_delegate respondsToSelector:@selector(fetchStart:alwaysLogString:)]) {                [_delegate fetchStart:self alwaysLogString:@"alwaysLog"];            }

        很容易用代码查出某个委托对象是否能响应特定的选择子,可是如果频繁的执行此操作的话,那么除了第一次检测的结果有用之外,后续的检测可能都是多余的。如果委托对象本身没变,那么不太可能会突然响应某个原来不能相应的方法,也不太会突然无法响应某个原来可以响应的方法。因此我们通常把委托对象能否响应某个协议方法这一信息缓存起来,以优化程序效率。

        将方法响应能力缓存起来的最佳途径就是使用“位段”数据类型。我们可以把结构体中某个字段所占用的二进制位个数设定为特定的值。比如这样:

struct {        unsigned int fieldA :8;        unsigned int fieldA :4;        unsigned int fieldA :2;        unsigned int fieldA :1;    }

    在结构体中,fieldA位段将占用8个二进制位,fieldB占用4个,fieldC占用两个,fieldD占用一个。于是,fieldA可以表示0至255之间的值,而fiedD则可以表示0或1这两个值。我们可以像fieldD这样把委托对象是否实现了协议中的相关方法这一信息缓存起来。如果创建的结构体中只有大小为1的位段,那么就能把许多Boolean值塞入一小块数据里面了。我们可以在实例中嵌入一个含有位段的结构体作为其实例变量,而结构体中的每个位段则表示delegate对象是否实现了协议中的相关方法。用法如下:

#import "WXKSimulateFetcher.h"@interface WXKSimulateFetcher () {    struct {        unsigned int didStartLog     :1;        unsigned int didAlwaysLog    :1;    }_delegateFlags;}@property (nonatomic, strong) dispatch_source_t timer;@end@implementation WXKSimulateFetcher- (void)doLog {    if (_delegateFlags.didStartLog) {        [_delegate fetchStart:self alwaysLogString:@"startLog"];    }        /*     使用定时器模拟频繁回调     */    __block int count = 0;    dispatch_queue_t queue = dispatch_get_main_queue();    self.timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue);    dispatch_time_t start = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.0 * NSEC_PER_SEC));    uint64_t interval = (uint64_t)(1.0 * NSEC_PER_SEC);    dispatch_source_set_timer(self.timer, start, interval, 0);    dispatch_source_set_event_handler(self.timer, ^{        if ([_delegate respondsToSelector:@selector(fetchStart:alwaysLogString:)]) {                [_delegate fetchStart:self alwaysLogString:@"alwaysLog"];            }        count++;        if (count == 10) {            dispatch_cancel(self.timer);            self.timer = nil;        }    });    dispatch_resume(self.timer);}- (void)setDelegate:(id
)delegate { _delegate = delegate; _delegateFlags.didStartLog = [delegate respondsToSelector:@selector(fetchStart:didStartLogString:)]; _delegateFlags.didAlwaysLog = [delegate respondsToSelector:@selector(fetchStart:alwaysLogString:)];}@end

        这样的话每次调用delegate的相关方法之前,就不用频繁检测了。

转载于:https://www.cnblogs.com/byxixiblogs/p/8352036.html

你可能感兴趣的文章
php cookie
查看>>
linux下redis安装
查看>>
弃 Java 而使用 Kotlin 的你后悔了吗?| kotlin将会是最好的开发语言
查看>>
JavaScript 数据类型
查看>>
量子通信和大数据最有市场突破前景
查看>>
StringBuilder用法小结
查看>>
对‘初学者应该选择哪种编程语言’的回答——计算机达人成长之路(38)
查看>>
如何申请开通微信多客服功能
查看>>
Sr_C++_Engineer_(LBS_Engine@Global Map Dept.)
查看>>
非监督学习算法:异常检测
查看>>
App开发中甲乙方冲突会闹出啥后果?H5 APP 开发可以改变现状吗
查看>>
jquery的checkbox,radio,select等方法总结
查看>>
Linux coredump
查看>>
Ubuntu 10.04安装水晶(Mercury)无线网卡驱动
查看>>
Myeclipes快捷键
查看>>
我的友情链接
查看>>
ToRPC:一个双向RPC的Python实现
查看>>
netty框架的学习笔记 + 一个netty实现websocket通信案例
查看>>
我的友情链接
查看>>
nginx在reload时候报错invalid PID number
查看>>