美文网首页开发技巧分类
OC限制函数调用的频率

OC限制函数调用的频率

作者: 纸简书生 | 来源:发表于2017-12-14 18:43 被阅读121次

最近抽空闲的时间看了一些算法相关的,刷刷LeetCode。实在感觉脑子不好使。想到前段时间处理了一个挺好玩的问题——限制GCD调用的频率。后来扩展到了限制函数调用。这里顺便总结一下。

本来想写详细点,😱,太懒了,这里只给出了基本思路和核心代码。

思路

为了达到限制调用频率的目的,很容易联想到throttle,也就是限流。最开始是从网络节流了解到这个基础名词的。简单来理解就是:对要处理的数据进行流量处理,限制频率。不是很清楚的可以看看这篇文章iOS编程中throttle那些事

大致有三种:1、一定时间内,以最早的数据为准。2、一定时间内,以最后的数据为准。3、如果时间在一定时间内,有新的数据来了,从新开始计时。

一定时间内很简单的可以通过比较上次时间和当前时间来比较,剩下的就是如何取消之前已经产生的数据。这里有两个思路,一个是用最新的覆盖掉之前的数据,二是直接把老数据删掉,重新构造新的数据。

可能看起来不清楚,现在就用实际例子来说。

GCD Throttle

需要用到的作料:dispatch_source_t,dispatch_queue_t,dispatch_source_set_timer
我们可以比较简单的通过dispatch_source_t来实现GCD的Throttle。得益于GCD提供了取消source的方法dispatch_source_cancel。

核心思路就是延迟特定时间调用一个任务,如果这段时间来新的任务了就取消掉之间的,如果时间到了就执行任务,需要创建一个对象、或者数组来保存之前的sourcer。代码很简单:

 dispatch_source_t source = scheduledSources[key];
        
//如果有了就取消掉,达到忽略中间的,调用最新的
if (source) {
    dispatch_source_cancel(source);
}

dispatch_source_t source = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue);
        dispatch_source_set_timer(source, dispatch_time(DISPATCH_TIME_NOW, threshold * NSEC_PER_SEC), DISPATCH_TIME_FOREVER, 0);
        dispatch_source_set_event_handler(source, ^{
            block();
            dispatch_source_cancel(source);
            [scheduledSources removeObjectForKey:key];
        });
        dispatch_resume(source);

基本的思路就是这样。如果想要写得更加通用一些,就是把需要变化的参数化就可以了。

常规的消息发送Throttle

如果想解决常规发送消息进行Throttle。这个挺麻烦的。因为RuntTime没有直接提供取消方法执行方式。

这里有几个思路:

  1. 因为上面已经实现了GCD Throttle调用,那么用GCD的方式把常规的方法调用包装一层就可以实现了。
  2. 利用Runtime消息转发,转发到自定义的方法进行延迟处理。具体逻辑可以看看

给类添加一个新的方法 fixed_selector,对应实现为 rule.selector 的 IMP。
利用 Objective-C runtime 消息转发机制,将 rule.selector 对应的 IMP 改成 _objc_msgForward 从而触发调用 forwardInvocation: 方法。
将 forwardInvocation: 的实现替换为自己实现的 IMP,并在自己实现的逻辑中将 invocation.selector 设为 fixed_selector。并限制 [invocation invoke] 的调用频率。

这里有个非常不错的库,已经把这个功能实现。Objective-C Message Throttle and Debounce

相关文章

  • OC限制函数调用的频率

    最近抽空闲的时间看了一些算法相关的,刷刷LeetCode。实在感觉脑子不好使。想到前段时间处理了一个挺好玩的问题—...

  • 限制一定时间内重复调用方法

    有时候我们要限制一些函数的调用频率,比如自动刷新,一分钟内不论谁调用这个函数,只能调用一次.这里提供一个简单好用的...

  • 2、block的本质是什么?有几种block?分别是怎样产生的?

    block是封装了函数调用以及函数调用环境的oc对象

  • Block本质-数据结构(-)

    Block的本质是封装了函数调用和函数调用环境的oc对象

  • block 笔记

    block本质是OC对象(封装了函数调用以及调用环境的OC对象) 本质

  • OC基础-Block(1)

    OC基础- blockBlock:本质:一个OC对象,一个封装了函数调用以及函数调用环境的OC对象 先定义一个简单...

  • 3,消息转发机制

    1,OC方法的调用 OC中的方法调用其实都是转成了objc_msgSend函数的调用,给receiver(方法调用...

  • objc_msgSend调用流程

    oc的方法调用 OC中的方法调用其实都是转成了objc_msgSend函数的调用,给receiver(方法调用者)...

  • 七.Block初识

    block的原理是什么?本质是什么?本质是OC对象,block封装了函数调用以及函数调用环境的OC对象 __blo...

  • iOS Block

    block本质block是封装了函数调用以及函数调用环境的OC对象(它内部也有个isa指针) 函数调用环境:函数调...

网友评论

    本文标题:OC限制函数调用的频率

    本文链接:https://www.haomeiwen.com/subject/ooflwxtx.html