我有一个异步调用多次的函数。每次我需要它做的是等待几个运行循环(或只需0.1秒就可以了),以确保它不会被其他任何地方调用。如果从其他地方调用它,请跳过该函数并让最新的调用执行代码(而代码会等待一小段时间检查它是否再次被调用)。
它只需要执行一次代码块,但它需要执行最新的数据。同时发生几次重要数据更新的可能性很高。可以把它想象成一个"检查没有更重要信息的人现在应该运行这个代码"。
这可能吗?我该怎么做呢?
答案 0 :(得分:3)
这就是你想要的吗?
[NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(delayExecuteMethod) object:nil];
[self performSelector:@selector(delayExecuteMethod) withObject:nil afterDelay:0.1];
答案 1 :(得分:0)
我写了一个类别来处理这个问题
#import <Foundation/Foundation.h>
@interface NSObject (XLCDelayedPerform)
- (void)xlc_setNeedsPerformSelector:(SEL)selector withObject:(id)obj;
- (void)xlc_setNeedsPerformSelector:(SEL)selector withObject:(id)obj withinInterval:(NSTimeInterval)interval;
- (void)xlc_performSelectorIfNeeded:(SEL)selector;
@end
#import "NSObject+XLCDelayedPerform.h"
#import <objc/runtime.h>
@implementation NSObject (XLCDelayedPerform)
static const void *delayedPerformInfoKey = &delayedPerformInfoKey;
- (void)xlc_setNeedsPerformSelector:(SEL)selector withObject:(id)obj {
[self xlc_setNeedsPerformSelector:selector withObject:obj withinInterval:0];
}
- (void)xlc_setNeedsPerformSelector:(SEL)selector withObject:(id)obj withinInterval:(NSTimeInterval)interval {
NSMutableDictionary *dict = objc_getAssociatedObject(self, delayedPerformInfoKey);
if (!dict) {
dict = [NSMutableDictionary dictionary];
objc_setAssociatedObject(self, delayedPerformInfoKey, dict, OBJC_ASSOCIATION_RETAIN);
}
NSString *strSel = NSStringFromSelector(selector);
id key = obj ? @[strSel, obj] : @[strSel];
NSTimer *timer = dict[key];
if (!timer) {
timer = [NSTimer scheduledTimerWithTimeInterval:interval
target:self
selector:@selector(xlc_delayedPerformSelectorOnTimer:)
userInfo:key
repeats:NO];
dict[key] = timer;
}
}
- (void)xlc_performSelectorIfNeeded:(SEL)selector {
NSMutableDictionary *dict = objc_getAssociatedObject(self, delayedPerformInfoKey);
NSString *strSel = NSStringFromSelector(selector);
NSTimer *timer = dict[strSel];
[timer fire];
}
#pragma mark - private
- (void)xlc_delayedPerformSelectorOnTimer:(NSTimer *)timer {
NSArray *info = timer.userInfo;
NSMutableDictionary *dict = objc_getAssociatedObject(self, delayedPerformInfoKey);
[dict removeObjectForKey:info];
id arg = info.count == 1 ? nil : info[1];
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
[self performSelector:NSSelectorFromString(info[0]) withObject:arg];
#pragma clang diagnostic pop
}
@end
例如
id obj = // something;
[obj xlc_setNeedsPerformSelector:@selector(dowork) withObject:nil];
[obj xlc_setNeedsPerformSelector:@selector(dowork) withObject:nil];
// [obj dowork] is called once on next runloop
答案 2 :(得分:0)
我不确定您正在寻找什么样的界面,但使用私人队列和计数器应该允许您构建这种控件。这是一种概念验证。您必须修改程序以适合您的具体情况。
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 CoalesceExecutions [98519:303]点击。
2014-06-04 03:40:33.565 CoalesceExecutions [98519:303]点击。
2014-06-04 03:40:34.066 CoalesceExecutions [98519:303]通过了 2014-06-04 03:40:34.600 CoalesceExecutions [98519:303]点击。
2014-06-04 03:40:34.802 CoalesceExecutions [98519:303]点击。
2014-06-04 03:40:35.304 CoalesceExecutions [98519:303]通过了 2014-06-04 03:40:35.342 CoalesceExecutions [98519:303]点击。
2014-06-04 03:40:35.623 CoalesceExecutions [98519:303]点击。
2014-06-04 03:40:36.085 CoalesceExecutions [98519:303]点击。
2014-06-04 03:40:36.585 CoalesceExecutions [98519:303]通过了 2014-06-04 03:40:40.955 CoalesceExecutions [98519:303]点击。
2014-06-04 03:40:41.135 CoalesceExecutions [98519:303]点击。
2014-06-04 03:40:41.315 CoalesceExecutions [98519:303]点击。
2014-06-04 03:40:41.518 CoalesceExecutions [98519:303]点击。
2014-06-04 03:40:41.698 CoalesceExecutions [98519:303]点击。
2014-06-04 03:40:41.878 CoalesceExecutions [98519:303]点击。
2014-06-04 03:40:42.047 CoalesceExecutions [98519:303]点击。
2014-06-04 03:40:42.238 CoalesceExecutions [98519:303]点击。
2014-06-04 03:40:42.429 CoalesceExecutions [98519:303]点击。
2014-06-04 03:40:42.598 CoalesceExecutions [98519:303]点击。
2014-06-04 03:40:42.789 CoalesceExecutions [98519:303]点击。
2014-06-04 03:40:42.980 CoalesceExecutions [98519:303]点击。
2014-06-04 03:40:43.482 CoalesceExecutions [98519:303]通过了 2014-06-04 03:40:44.894 CoalesceExecutions [98519:303]点击。
2014-06-04 03:40:45.395 CoalesceExecutions [98519:303]通过了 2014-06-04 03:40:46.019 CoalesceExecutions [98519:303]点击。
2014-06-04 03:40:46.520 CoalesceExecutions [98519:303]通过了 2014-06-04 03:40:48.054 CoalesceExecutions [98519:303]点击。
2014-06-04 03:40:48.346 CoalesceExecutions [98519:303]点击。
2014-06-04 03:40:48.847 CoalesceExecutions [98519:303]通过了 2014-06-04 03:40:49.055 CoalesceExecutions [98519:303]点击。
2014-06-04 03:40:49.336 CoalesceExecutions [98519:303]点击。
2014-06-04 03:40:49.837 CoalesceExecutions [98519:303]通过