我有一个发送错误消息的函数 (sendError
)。然后 5 秒后将其删除,如下所示:
-(void)sendError:(NSString*)message{
_errorMessage.stringValue = message;
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
_errorMessage.stringValue = @"";
});
}
问题是,如果按钮运行一次,然后 3 秒后再次运行,则第二次运行该消息将在 2 秒后删除,而不是 5 秒。
如何取消之前的调度并编写新的调度(覆盖)。
最佳答案
有几种方法可以做到这一点。首先,您可以停止使用 GCD 并返回到早期的机制,-performSelector:withObject:afterDelay:
。这里的优点是有一个方法 +cancelPreviousPerformRequestsWithTarget:selector:object:
可以取消仍待处理的执行请求。
-(void)sendError:(NSString*)message{
_errorMessage.stringValue = message;
[NSObject cancelPreviousPerformRequestsWithTarget:_errorMessage selector:@selector(setStringValue:) object:@""];
[_errorMessage performSelector:@selector(setStringValue:) withObject:@"" afterDelay:5];
}
如果您想继续使用 GCD,那么您需要自行跟踪取消情况。一种方法是保留“一代”计数。因此,假设存在一个名为 _errorGeneration
的 NSUInteger
实例变量。
-(void)sendError:(NSString*)message{
_errorMessage.stringValue = message;
_errorGeneration++;
NSUInteger capturedGeneration = _errorGeneration;
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
if (_errorGeneration == capturedGeneration)
_errorMessage.stringValue = @"";
});
}
基本上,您不会取消分派(dispatch)的任务(因为您不能),但如果它已过时,您可以让它不执行任何操作。
关于objective-c - 覆盖调度命令,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41990860/