我编写了这两个实用函数:
+ (void)dispatch:(void (^)())f afterDelay:(float)delay {
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delay*NSEC_PER_SEC)),
dispatch_get_main_queue(),
f);
}
+ (void)dispatch:(void (^)())f withInterval:(float)delay {
void (^_f)() = nil; // <-- A
_f = ^{
f();
[self dispatch:_f afterDelay:delay]; // <-- B
};
[self dispatch:_f afterDelay:delay];
}
这个想法是,你可以调用:
[self dispatch:block afterDelay:delay]; - 以便在特定时间后执行块
和
[self dispatch:block withInterval:delay]; - 以便定期执行块
现在,如果我直接调用 dispatch:withInterval:,程序将在运行时出现错误。因为当程序尝试在B行执行时,_f的值将为nil;而这又会导致_f保持对A处_f的引用。
如果我将A改成以下内容,则可以解决这个问题:
__block void (^_f)() = nil;
在这里,我强调对_f的强引用,因此当代码到达B时,_f的值是最终分配给它的值。问题在于我正在遭受保留周期的影响。
最后,我可以将A更改为:
__block void (^_f)() __weak = nil;
这样做应该可以解决两个问题,但是我发现当代码到达B时,_f的值再次变为nil,因为在它被评估时,_f已经被释放了。
我有几个问题:
- 在最后一种情况下,为什么_f会被释放?如何告诉ARC至少保留块直到下一个调度调用?
- 编写这些函数的最佳(并且符合ARC标准)方法是什么?
感谢您的时间。
void (^)(void)
的类型 --dispatch_block_t
。 - jscs