所以这就是我所拥有的:
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 0.1*NSEC_PER_SEC), dispatch_get_current_queue(), ^{
bool ready = some_function();
if( ready ) {
do_smth_here()
} else {
//invoke this block one more time after 0.1 sec
}
});
问题是如何获得对当前块的引用?
答案 0 :(得分:4)
我没有跳过上面显示的箍,而是通常声明一个我可以调用的实例方法,在内部,根据需要处理重新触发。这样,任何给定的块都是一次性的,但重新触发会创建一个新块。
只要块创建不是非常昂贵 - 如果状态来自封装实例方法的任何东西,它就不会 - 它足够有效并且简单得多。
- (void) retriggerMethod
{
... do stuff here, assuming you want to do it on first invocation ...
dispatch_after( ..., ^{
[self retriggerMethod];
});
}
您可以根据需要对其进行重组。如果你想要防止同时重新触发等,你可以轻松添加一个BOOL实例变量......
这也提供了一个方便的取消钩子;只需在实例中添加一个BOOL,指示下一次调用是否应该执行任何操作并重新安排。
答案 1 :(得分:3)
杰弗里·托马斯的答案很接近,但是在ARC下,它会泄漏阻塞,没有ARC,它会崩溃。
如果没有ARC,__block
变量不会保留它引用的内容。块在堆栈上创建。所以callback
变量指向堆栈上的块。第一次(在块之外)将callback
传递给dispatch_after
时,dispatch_after
成功地在堆上复制了块。但是当调用该副本并再次将callback
传递给dispatch_after
时,callback
是一个悬空指针(对于堆栈中现在被破坏的块),dispatch_after
将(通常)崩溃。
使用ARC,块类型的__block
变量(如callback
)会自动将块复制到堆中。所以你没有得到崩溃。但是使用ARC,__block
变量会保留它引用的对象(或块)。这导致保留周期:块引用自身。 Xcode会在递归dispatch_after
调用时向您显示警告:“在此块中强烈捕获'回调'可能会导致保留周期”。
要解决这些问题,您可以显式复制块(将其从堆栈移动到MRC下的堆)并将callback
设置为nil(在ARC下)或释放它(在MRC下)以防止泄漏它:
__block void (^callback)() = [^{
if(stop_) {
NSLog(@"all done");
#if __has_feature(objc_arc)
callback = nil; // break retain cycle
#else
[callback release];
#endif
} else {
NSLog(@"still going");
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 1*NSEC_PER_SEC), dispatch_get_current_queue(), callback);
}
} copy];
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 1*NSEC_PER_SEC), dispatch_get_current_queue(), callback);
显然你可以删除#if
并使用适合你的内存管理的分支。
答案 2 :(得分:1)
我认为这是您要寻找的代码:
__block void (^callback)();
callback = ^{
bool ready = some_function();
if( ready ) {
do_smth_here()
} else {
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 0.1*NSEC_PER_SEC), dispatch_get_current_queue(), callback);
}
};
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 0.1*NSEC_PER_SEC), dispatch_get_current_queue(), callback);