我有一个for循环,我希望在迭代之间添加延迟。我已将waitUntilDone更改为YES并获得相同的结果。我的数组中只有两个数字,两个数字在五秒后调用,而不是:
0s - 没什么 5s - 座叫 10s-座叫
for(NSNumber* transaction in gainsArray) {
double delayInSeconds = 5.0;
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC));
dispatch_after(popTime, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(void) {
NSLog(@"Block");
[self performSelectorOnMainThread:@selector(private_addTransactionToBankroll:)
withObject:transaction waitUntilDone:NO];
});
}
2015-06-16 20:11:06.485 TestApp[97027:6251126] Block
2015-06-16 20:11:06.485 TestApp[97027:6251127] Block
如果重要,我正在使用Cocos2d
答案 0 :(得分:6)
for循环将一个接一个地发送,所以它们基本上会延迟相同的时间 而是为每个设置不同的增加延迟:
double delayInSeconds = 0.0;
for(NSNumber* transaction in gainsArray)
{
delayInSeconds += 5.0;
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC));
dispatch_after(popTime, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(void)
{
NSLog(@"Block");
[self performSelectorOnMainThread:@selector(private_addTransactionToBankroll:)
withObject:transaction
waitUntilDone:NO];
});
}
答案 1 :(得分:1)
@zaph有一个非常好的解决方案。我以为我会从不同的角度尝试。由于Objective-C是 Objective -C,为什么不定义某种对象来进行这种定时循环?提示:这存在。我们可以使用NSTimer及其userInfo属性来解决这个问题。我认为解决方案有点优雅,如果不是讨厌的黑客。
// Somewhere in code.... to start the 'loop'
NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:5.0
target:self
action:@selector(processNextTransaction:)
userInfo:@{
@"gains": [gainsArray mutableCopy]
}
repeats:NO];
// What handles each 'iteration' of your 'loop'
- (void)processNextTransaction:(NSTimer *)loopTimer {
NSMutableArray *gains = [loopTimer.userInfo objectForKey:@"gains"];
if(gains && gains.count > 0) {
id transaction = [gains firstObject];
[gains removeObjectAtIndex:0]; // NSMutableArray should really return the object we're removing, but it doesn't...
[self private_addTransactionToBankroll:transaction];
NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:5.0
target:self
action:@selector(processNextTransaction:)
userInfo:@{
@"gains": gains
}
repeats:NO];
}
}
我会通过添加到运行循环来检查NSTimer是否被保留。如果不是这种情况,你应该将对它的引用存储为管理所有这些的任何类的属性。
值得注意的是,因为NSTimers默认安装在主运行循环上,所以你不必担心所有的GCD内容。然后,如果这项工作非常困难,您可能希望-processNextTransaction:
将其工作卸载到另一个GCD队列,然后返回主队列以初始化NSTimer实例。
请务必使用-scheduledTimer...
方法; timer...
上的NSTimer
类方法不会在任何循环上安装它,并且对象只是在空间中无所事事。不要做repeats:YES
,这将是悲剧性的,因为你的计时器附带在运行循环上,没有任何引用指向它们知道如何或在何处阻止它们。这通常是一件坏事。
为了避免EXC_BAD_ACCESS
例外,永远不要释放NSTimer
将调用其方法的对象,如果该计时器尚未触发。您可能希望将待处理的NSTimer
存储在类的属性中,以便您可以处理此类事情。如果它是一个管理所有这些(通常是)的ViewController,那么我将使用以下代码来清理-viewWillDisappear
上的计时器。 (这假设您要为某些@property
,self.timer
)
- (void)viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
if(self.timer) {
[self.timer invalidate]; // -invalidate removes it from the run loop.
self.timer = nil; // Stop pointing at it so ARC destroys it.
}
}