在 libdispatch (也称为 Grand Central Dispatch) 之上实现的一个非常薄的 API 和概念,用于 Cocoa Objective-C 代码。
我是个懒人,所以当我不得不写很多的代码来做这样一些众所周知的事情,比如在不同的调度队列中安排各种代码块的时候,就会感到痛苦。这个小工具让我用更少的代码完成工作,并且结果也更容易阅读。
首先,使用纯 libdispatch
dispatch_queue_t parentQueue = dispatch_get_current_queue();
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSLog(@"Block #1 on queue '%s' (parentQueue: '%s')",
dispatch_queue_get_label(dispatch_get_current_queue()),
dispatch_queue_get_label(parentQueue));
dispatch_queue_t parentQueue2 = dispatch_get_current_queue();
dispatch_async(dispatch_get_main_queue(), ^{
NSLog(@"Block #2 on queue '%s'",
dispatch_queue_get_label(dispatch_get_current_queue()));
dispatch_async(parentQueue2, ^{
NSLog(@"Block #3 on queue '%s'",
dispatch_queue_get_label(dispatch_get_current_queue()));
exit(0);
});
});
});
现在,使用 LazyDispatch
sched_background ^(DQueue parentQueue){
NSLog(@"Block #1 on queue '%s' (parentQueue: '%s')",
DQueueID(__queue), DQueueID(parentQueue));
sched_main ^(DQueue parentQueue){
NSLog(@"Block #2 on queue '%s'", DQueueID(__queue));
sched(parentQueue) ^{
NSLog(@"Block #3 on queue '%s'", DQueueID(__queue));
};
};
};
Block #1 on queue 'com.apple.root.default-priority' (parentQueue: 'com.apple.main-thread')
Block #2 on queue 'com.apple.main-thread'
Block #3 on queue 'com.apple.root.default-priority'
看吧。简单多了,性能相同,因为没有增加任何实际的开销。我们只是把东西重新表述了一下,使其更易于阅读。
哇!我现在可以玩得更开心了!
还有定时器。我们都很爱它们,不是吗?
sched_delay(1, ^{
NSLog(@"Delayed block executed after one second");
});
就像 JavaScript 一样,定时器可以被取消
DTimer timer = sched_interval(13.37, ^{
NSLog(@"Delayed block sez hi");
});
//...
DTimerStop(timer);
DQueue
— 一个调度队列(dispatch_queue_t
的别名)DBlock
— 一个块(dispatch_block_t
的别名)DTimer
— 一个定时器(dispatch_source_t
的别名)__queue
→ DQueue
— 当前队列__main_queue
→ DQueue
— 主队列sched_background ^([DQueue parentQueue]) → block
在后台队列中安排一个块。块可以接受一个可选参数,这将是从 sched_background
调用的队列。表达式的结果是块本身。
这对于调用回调并将控制权返回到同一队列非常有用,例如
- (void)doSomethingFunkyWithCallback:(DBlock)callback {
sched_background ^(DQueue parentQueue){
// work work work ...
sched(parentQueue) callback;
};
}
sched_main ^([DQueue parentQueue]) → block
在主队列中安排一个块。块可以接受一个可选参数,这将是从 sched_main
调用的队列。表达式的结果是块本身。
sched(DQueue queue) ^([DQueue parentQueue]) → block
在队列中安排一个块。该块可以选择接受一个参数,该参数将是调用 sched
后的队列。表达式的结果是该块本身。
const char* DQueueID(DQueue queue)
访问 queue
(其“标签”)的易读标识符
DTimer sched_delay(NSTimeInterval delay, ^([DTimer[, DQueue]]))
在当前队列中安排一个块,该块将在 delay
秒后执行。您可以通过调用(从该函数返回的)DTimer
对象上的 DTimerStop
来在计时器触发前取消计时光标。
示例
// Schedule a block to be run after a delay of one second
sched_delay(1, ^{
NSLog(@"Delayed block triggered");
});
DTimer sched_interval(NSTimeInterval interval, ^([DTimer[, DQueue]]))
在当前队列中安排一个块,每隔 interval
秒执行一次。您需要在不再需要计时器时调用 DTimerStop(timer)
。
示例
// Schedule a block to be run every 1.1 seconds
sched_interval(1.1, ^{
NSLog(@"Perpetual block triggered");
});
DTimer sched_timer(DQueue queue, NSTimeInterval delay, NSTimeInterval interval, ^([DTimer[, DQueue]]))
在 queue
上安排一个计时器,在 delay
秒后开始运行,并每隔 interval
重复。
如果 interval
具有正值,计时器将每 interval
秒重复一次。在这种情况下,您负责通过调用 DTimerStop(timer)
停止计时光标。如果 interval
为零或负数,计时器只触发一次,然后自动停止。
示例
// Start a timer on `fooQueue` after 1.5 seconds, triggering in 3.5 second intervals
sched_timer(fooQueue, 1.5, 3.5, ^(DTimer timer){
NSLog(@"Timer %@ triggered on foo queue", timer);
});
DTimer DTimerCreate(DQueue queue, NSTimeInterval delay, NSTimeInterval interval, ^([DTimer[, DQueue]]))
与 sched_timer
相似,但仅创建计时器(不会对其进行安排)。您需要调用 DTimerResume
以安排计时器。
示例
DTimer timer = DTimerCreate(fooQueue, 1.5, 3.5, ^(DTimer timer){
NSLog(@"Timer %@ triggered on foo queue", timer);
});
// ...
DTimerResume(timer);
DTimer DTimerResume(DTimer timer)
安排尚未安排的计时器(由 DTimerPause
暂停或由 DTimerCreate
刚创建。)
每次调用 DTimerResume
都必须平衡一个调用到 DTimerPause
,否则将出现内存违规,可能导致所有东西崩溃。这是 libdispatch 的特性,以使用容错和效率进行交换。请注意,从 sched_delay
、sched_interval
和 sched_timer
返回的计时器已经恢复了。
DTimer DTimerPause(DTimer timer)
取消已安排的计时器。在暂停计时器并在稍后恢复它时,触发时间不会根据计时器暂停期间的时间进行调整。
DTimer DTimerSetInterval(DTimer timer, NSTimeInterval interval)
修改和重置计时器的间隔。
如果计时器源已被取消,调用此函数不会产生影响。
示例
// Execute a block five times with 1 second interval, then change the interval to
// execute the block with 2 seconds interval.
__block int triggerCount = 0;
sched_interval(1.0, ^(DTimer timer){
NSLog(@"Perpetual block triggered");
if (++triggerCount == 5) {
DTimerSetInterval(timer, 2.0);
}
});
void DTimerStop(DTimer timer)
取消操作将防止进一步调用指定定时器的处理程序块,但不会中断正在执行的处理程序块。
版权所有(c)2012 拉斯穆斯· andersson http://rsms.me/
在此特此准许任何人免费获取此软件及其相关文档(以下简称“软件”)副本,无论出于任何目的使用、复制、修改、合并、发布、分发、再许可或出售软件副本,并允许向软件提供副本的个人执行上述行为,前提是遵守以下条件
上述版权声明和本许可声明应包含在软件的所有副本或主要部分中。
软件按“原样”提供,不提供任何形式的担保,包括但不限于适销性、针对特定目的的适用性和非侵权性担保。在任何情况下,作者或版权所有者对任何索赔、损害或其他责任,无论源于合同、侵权或其他,因软件或其使用或其他方式产生或与之相关均不承担任何责任。