Ios Objective-C异步任务。如何在多次调用时只运行一次函数?

Ios Objective-C异步任务。如何在多次调用时只运行一次函数?,ios,objective-c,Ios,Objective C,我有一个函数,可以异步调用多次。我每次需要它做的是等待几个运行循环(或者只需0.1秒就可以了),以确保它不会从其他任何地方被调用。如果它是从其他地方调用的,则跳过该函数,让最新的调用执行代码(这反过来会等待一小段时间来检查它是否再次被调用) 这是一个只需要执行一次的代码块,但它需要使用最新的数据来执行。同时进行几次重要数据更新的可能性很高。可以将其视为“检查是否没有任何拥有更重要信息的人现在正在运行此代码” 这可能吗?我该怎么做呢?我写了一个类别来处理这个问题 这是你想要的吗 [NSObjec

我有一个函数,可以异步调用多次。我每次需要它做的是等待几个运行循环(或者只需0.1秒就可以了),以确保它不会从其他任何地方被调用。如果它是从其他地方调用的,则跳过该函数,让最新的调用执行代码(这反过来会等待一小段时间来检查它是否再次被调用)

这是一个只需要执行一次的代码块,但它需要使用最新的数据来执行。同时进行几次重要数据更新的可能性很高。可以将其视为“检查是否没有任何拥有更重要信息的人现在正在运行此代码”


这可能吗?我该怎么做呢?

我写了一个类别来处理这个问题

这是你想要的吗

[NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(delayExecuteMethod) object:nil];
[self performSelector:@selector(delayExecuteMethod) withObject:nil afterDelay:0.1];

我不确定您正在寻找什么样的接口,但是使用专用队列和计数器应该允许您构建这种控制。这是一种概念证明。你必须修改程序以适应你的具体情况

void coalesce_execution(dispatch_block_t executable,
                         dispatch_queue_t execution_queue,
                         double wait_interval)
{
    // Create a counter and a queue to synchronize access to it
    static unsigned int num_waiting = 0;
    static dispatch_queue_t wait_queue;
    static dispatch_once_t once_token;
    dispatch_once(&once_token, ^{
        wait_queue = dispatch_queue_create("your.label.here",
                                           DISPATCH_QUEUE_PRIORITY_DEFAULT);
    });

    // Increment shared counter on queue
    dispatch_async(wait_queue, ^{
        num_waiting++;
    });

    // Wait, then decrement counter on queue
    dispatch_time_t wait_time = dispatch_time(DISPATCH_TIME_NOW,
                                              (int64_t)(wait_interval * NSEC_PER_SEC));
    dispatch_after(wait_time, wait_queue, ^(void){
        num_waiting--;
        // If counter is zero, execute: nothing else came within the cutoff.
        if( 0 == num_waiting ){
            dispatch_async(execution_queue, executable);
        }
    });
}
按如下方式连接按钮:

- (IBAction)executeCoalescing:(id)sender 
{

    NSLog(@"Clicked.");
    coalesce_executions(^{ NSLog(@"Got through");  },
                        dispatch_get_main_queue(), 0.5);

}
沿着以下几行给出输出:

2014-06-04 03:40:33.374合并[98519:303]点击。
2014-06-04 03:40:33.565合并执行[98519:303]已单击。
2014-06-04 03:40:34.066联合执行[98519:303]通过
2014-06-04 03:40:34.600合并执行[98519:303]已单击。
2014-06-04 03:40:34.802合并执行[98519:303]已单击。
2014-06-04 03:40:35.304联合执行[98519:303]通过
2014-06-04 03:40:35.342合并执行[98519:303]已单击。
2014-06-04 03:40:35.623合并[98519:303]点击。
2014-06-04 03:40:36.085合并执行[98519:303]已单击。
2014-06-04 03:40:36.585联合执行[98519:303]通过
2014-06-04 03:40:40.955合并执行[98519:303]已单击。
2014-06-04 03:40:41.135合并执行[98519:303]已单击。
2014-06-04 03:40:41.315合并[98519:303]点击。
2014-06-04 03:40:41.518合并[98519:303]点击。
2014-06-04 03:40:41.698合并[98519:303]点击。
2014-06-04 03:40:41.878合并[98519:303]点击。
2014-06-04 03:40:42.047合并执行[98519:303]已单击。
2014-06-04 03:40:42.238合并[98519:303]点击。
2014-06-04 03:40:42.429合并执行[98519:303]已单击。
2014-06-04 03:40:42.598合并[98519:303]点击。
2014-06-04 03:40:42.789合并执行[98519:303]已单击。
2014-06-04 03:40:42.980合并[98519:303]点击。
2014-06-04 03:40:43.482合并执行[98519:303]通过
2014-06-04 03:40:44.894合并执行[98519:303]已单击。
2014-06-04 03:40:45.395联合执行[98519:303]通过
2014-06-04 03:40:46.019合并执行[98519:303]已单击。
2014-06-04 03:40:46.520联合执行[98519:303]通过
2014-06-04 03:40:48.054合并执行[98519:303]已单击。
2014-06-04 03:40:48.346合并执行[98519:303]已单击。
2014-06-04 03:40:48.847合并执行[98519:303]通过
2014-06-04 03:40:49.055合并[98519:303]点击。
2014-06-04 03:40:49.336合并[98519:303]点击。
2014-06-04 03:40:49.837联合执行[98519:303]通过


你不觉得这很危险吗?如果您将延迟设置为0.1秒,而第二次呼叫在0.10001秒后到来,该怎么办?这可能会对您有所帮助:类似:@matt it not。它实际上是一个触发我的函数的系统调用。这种情况在一个蓝色的月亮上只发生一次,但当它发生时,它似乎同时多次调用它,最后一次调用它时,它的数据是最正确的。有点奇怪,但是是的……不过我认为最好的方法(我最终就是这么做的)是重新设计东西,这样,如果我连续两次接到电话,就真的不要紧了。:)是的,很好很简单!谢谢
[NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(delayExecuteMethod) object:nil];
[self performSelector:@selector(delayExecuteMethod) withObject:nil afterDelay:0.1];
void coalesce_execution(dispatch_block_t executable,
                         dispatch_queue_t execution_queue,
                         double wait_interval)
{
    // Create a counter and a queue to synchronize access to it
    static unsigned int num_waiting = 0;
    static dispatch_queue_t wait_queue;
    static dispatch_once_t once_token;
    dispatch_once(&once_token, ^{
        wait_queue = dispatch_queue_create("your.label.here",
                                           DISPATCH_QUEUE_PRIORITY_DEFAULT);
    });

    // Increment shared counter on queue
    dispatch_async(wait_queue, ^{
        num_waiting++;
    });

    // Wait, then decrement counter on queue
    dispatch_time_t wait_time = dispatch_time(DISPATCH_TIME_NOW,
                                              (int64_t)(wait_interval * NSEC_PER_SEC));
    dispatch_after(wait_time, wait_queue, ^(void){
        num_waiting--;
        // If counter is zero, execute: nothing else came within the cutoff.
        if( 0 == num_waiting ){
            dispatch_async(execution_queue, executable);
        }
    });
}
- (IBAction)executeCoalescing:(id)sender 
{

    NSLog(@"Clicked.");
    coalesce_executions(^{ NSLog(@"Got through");  },
                        dispatch_get_main_queue(), 0.5);

}