lms*_*lms 37 cocoa cocoa-touch objective-c grand-central-dispatch nsrunloop
我希望能够block在下一个运行循环迭代中执行a .它是否在下一个运行循环的开始或结束时执行并不是那么重要,只是执行被推迟到当前运行循环中的所有代码都已完成执行.
我知道以下内容不起作用,因为它与主运行循环交错,所以我的代码可能会在下一个运行循环中执行,但它可能不会.
dispatch_async(dispatch_get_main_queue(),^{
//my code
});
Run Code Online (Sandbox Code Playgroud)
以下我认为遇到与上述相同的问题:
dispatch_after(DISPATCH_TIME_NOW, dispatch_get_main_queue(), ^(void){
//my code
});
Run Code Online (Sandbox Code Playgroud)
现在我相信以下内容可以正常工作,因为它放在当前运行循环的末尾(如果我错了,请纠正我),这实际上有用吗?
[self performSelector:@selector(myMethod) withObject:nil afterDelay:0];
Run Code Online (Sandbox Code Playgroud)
那个有0间隔的计时器怎么样?文档说明:If seconds is less than or equal to 0.0, this method chooses the nonnegative value of 0.1 milliseconds instead.这是否可以保证在下一次运行循环迭代中执行?
[NSTimer scheduledTimerWithTimeInterval:0 target:self selector:@selector(myMethod) userInfo:nil repeats:NO];
Run Code Online (Sandbox Code Playgroud)
这是我能想到的所有选项,但我仍然没有接近于在下一次运行循环迭代中执行一个块(而不是调用方法),并保证它不会更快.
rob*_*off 86
您可能不知道运行循环在每次迭代中执行的所有操作.(我之前没有研究过这个答案!)实际上,它CFRunLoop是开源CoreFoundation软件包的一部分,所以我们可以看看它究竟是什么.运行循环看起来大致如下:
while (true) {
Call kCFRunLoopBeforeTimers observer callbacks;
Call kCFRunLoopBeforeSources observer callbacks;
Perform blocks queued by CFRunLoopPerformBlock;
Call the callback of each version 0 CFRunLoopSource that has been signalled;
if (any version 0 source callbacks were called) {
Perform blocks newly queued by CFRunLoopPerformBlock;
}
if (I didn't drain the main queue on the last iteration
AND the main queue has any blocks waiting)
{
while (main queue has blocks) {
perform the next block on the main queue
}
} else {
Call kCFRunLoopBeforeWaiting observer callbacks;
Wait for a CFRunLoopSource to be signalled
OR for a timer to fire
OR for a block to be added to the main queue;
Call kCFRunLoopAfterWaiting observer callbacks;
if (the event was a timer) {
call CFRunLoopTimer callbacks for timers that should have fired by now
} else if (event was a block arriving on the main queue) {
while (main queue has blocks) {
perform the next block on the main queue
}
} else {
look up the version 1 CFRunLoopSource for the event
if (I found a version 1 source) {
call the source's callback
}
}
}
Perform blocks queued by CFRunLoopPerformBlock;
}
Run Code Online (Sandbox Code Playgroud)
您可以看到有多种方法可以挂钩运行循环.您可以CFRunLoopObserver为所需的任何"活动" 创建一个名称.您可以创建版本0 CFRunLoopSource并立即发出信号.您可以创建一对连接的CFMessagePorts,在版本1中包装一个CFRunLoopSource,并向其发送消息.你可以创建一个CFRunLoopTimer.您可以使用队列块dispatch_get_main_queue或CFRunLoopPerformBlock.
您需要根据计划块的时间以及何时需要调用块来决定使用哪些API.
例如,触摸在版本1源中处理,但是如果通过更新屏幕来处理触摸,则在提交核心动画事务之前实际不会执行该更新,这在kCFRunLoopBeforeWaiting观察者中发生.
现在假设您要在处理触摸时调度块,但是您希望在提交事务后执行该块.
您可以CFRunLoopObserver为kCFRunLoopBeforeWaiting活动添加自己的活动,但此观察者可能在Core Animation的观察者之前或之后运行,具体取决于您指定的顺序和Core Animation指定的顺序.(核心动画目前指定的订单为2000000,但未记录,因此可能会更改.)
要确保您的块在Core Animation的观察者之后运行,即使您的观察者在 Core Animation的观察者之前运行,也不要直接在观察者的回调中调用该块.而是dispatch_async在此时使用将块添加到主队列.将块放在主队列上会强制运行循环立即从其"等待"中唤醒.它将运行任何kCFRunLoopAfterWaiting观察者,然后它将耗尽主队列,此时它将运行你的块.
| 归档时间: |
|
| 查看次数: |
11077 次 |
| 最近记录: |