现在dispatch_get_current_queue
在 iOS 6 中已弃用,我如何使用dispatch_after
在当前队列中执行某些内容?
3 回答
评论中的各种链接并没有说“最好不要这样做”。他们说你做不到。您必须传递所需的队列或分派到已知队列。调度队列没有“当前”的概念。块通常从一个队列馈送到另一个队列(称为“定位”)。当您实际运行时,“当前”队列并没有真正意义,并且依赖它可能(并且历史上确实)导致死锁。dispatch_get_current_queue()
从来都不是用来调度的;这是一种调试方法。这就是它被删除的原因(因为人们把它当作有意义的东西对待)。
如果您需要这种更高级别的簿记,请使用NSOperationQueue
跟踪其原始队列的 an (并具有更简单的排队模型,使“原始队列”更有意义)。
UIKit 中使用了几种合适的方法:
- 将回调 dispatch_queue 作为参数传递(这可能是新 API 中最常见的方法)。有关示例,请参见
[NSURLConnection setDelegateQueue:]
或addObserverForName:object:queue:usingBlock:
。请注意,NSURLConnection
期望的是NSOperationQueue
,而不是dispatch_queue
。更高级别的 API 等等。 - 回调您所在的任何队列并将其留给接收者处理。这就是传统上回调的工作方式。
- 要求调用线程上有一个runloop,并在调用runloop上安排你的回调。这就是
NSURLConnection
排队之前的历史工作方式。 - 除非另有说明,否则请始终在知名队列之一(尤其是主队列)上进行回调。我不知道这是在 UIKit 中完成的,但我在应用程序代码中经常看到它,并且大多数时候是一种非常简单的方法。
手动创建一个队列并将您的调用代码和dispatch_after
代码分派到该队列上。这样你就可以保证两段代码都是从同一个队列中运行的。
不得不这样做很可能是因为需要破解。你可以用另一个 hack 来解决这个问题:
id block = ^foo() {
[self doSomething];
usleep(delay_in_us);
[self doSomehingOther];
}
而不是usleep()
您可能会考虑在运行循环中循环。
我不会推荐这种“方法”。更好的方法是使用一些方法,将队列作为参数,将块作为参数,然后在指定的队列上执行块。
顺便说一句,在块执行期间有一些方法可以检查它是否在特定队列上运行 - 分别在其任何父队列上运行,前提是您事先有对该队列的引用:使用 functionsdispatch_queue_set_specific
和dispatch_get_specific
.