需求:一组数据指令(1000个),每个模型(比如float time = 30ms)里保存有一个毫秒级的时间。然后执行第一个指令是在0ms,第二个指令是在30ms 第3个指令是在60ms,以此类推。那么执行完全部命令就是30 * 1000 = 30000ms .
1,如果你用for循环在里面用 [NSThread sleepForTimeInterval:0.03];是万万不行的。100%大于30s 误差在2s以上
CFAbsoluteTime startTime = CFAbsoluteTimeGetCurrent();
for(inti =0; i <1000; i++) {
[NSThread sleepForTimeInterval:0.03];
}
CFAbsoluteTime linkTime = (CFAbsoluteTimeGetCurrent() - startTime) * 1000;
NSLog(@"------cost time = %f ms(毫秒)", linkTime);// ------cost time = 30968.497992 ms(毫秒)
解决办法:
@property (nonatomic, assign) CFAbsoluteTime startTime;//全局记录开始的时间
@property (nonatomic, assign) BOOL stop;//记录是否停止所有延迟 yes 为全部停止
- (void)test
{
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{//放子线创建延迟
_startTime = CFAbsoluteTimeGetCurrent();
floattime =0;//单位s
for(inti =0; i <1000; i++) {
[self performSelector:@selector(timeoutMethod:)withObject:@(i)afterDelay:time];
time = time +0.03;
}
if (![NSRunLoop currentRunLoop].currentMode) {//只开启一次
[[NSRunLoop currentRunLoop] run];
}
});
}
- (void)timeoutMethod:(NSNumber*)num
{
if(self.stop) {
[NSObject cancelPreviousPerformRequestsWithTarget:self];//停止 一定要在当前线程调用。测试过在子线程创建的延迟,即使是在主线程也取消不了
return;
}
//在这里做你延迟后想做的事情
if([num isEqual:@(999)]) {//执行最后一条命令打印时间
CFAbsoluteTime linkTime = (CFAbsoluteTimeGetCurrent() - _startTime) * 1000;
NSLog(@"Linked in %f ms", linkTime );//Linked in 30004.699974 ms一般误差在10ms左右
}
}
当要某一时刻停止全部任务时用 [NSObject cancelPreviousPerformRequestsWithTarget:self];
(建议循环创建延迟 [self performSelector:@selector(timeoutMethod:)withObject:@(i)afterDelay:time]; 放在子线程,同时记得要开启runloop,如果放主线程,当你操作UI控件的时候(比如一直拖着tableview不放)timeoutMethod是不执行的,需要你放了拖拽tableview才会继续执行timeoutMethod延迟方法,当然把主线程的runloop改为在CommonMode,可以解决这种问题。
网友评论