忽略连续的performSelector:withObject:afterDelay:通过检查队列消息

时间:2014-04-10 02:29:50

标签: ios objective-c scheduled-tasks grand-central-dispatch performselector

我正在尝试使用performSelector:withObject:afterDelay:来快速更新快速更改的表格视图以显示日志消息:

  • 第一条新日志消息将在最小延迟(0.5秒)后安排表更新。
  • 应忽略该最小延迟之前的连续日志消息。
  • 更新表格视图后,可以再次安排新的更新。

Similar个问题通过先拨打cancelPreviousPerformRequestsWithTarget:来“重新安排”原始通话。

我也想知道是否:

  • GCD会更好(我相信会这样),如果它更简单(不确定)。
  • 我是否真的需要最小的刷新间隔,或者如果表视图已准备好再次更新,那么现在还有办法(0.5秒可能不必要很长或不够,具体取决于设备及其工作负载)。

对于有兴趣的人,我正在重构this

1 个答案:

答案 0 :(得分:1)

好好放弃performSelector并提出了一个运作良好的GCD解决方案:

创建一个串行队列_consoleQueue = dispatch_queue_create("console_queue", NULL)

消息处理代码,其中_updateScheduled用作忽略后续调用的标志。该标志仅在_consoleQueue中读取和修改,以确保一致性。

- (void)logMessage:(DDLogMessage *)logMessage
{
    dispatch_async(_consoleQueue, ^
    {
        [_newMessagesBuffer insertObject:logMessage
                                 atIndex:0];

        // Ignore subsequent calls when already scheduled
        if (_updateScheduled)
            return;

        NSTimeInterval timeToWaitForNextUpdate = _minIntervalToUpdate + _lastUpdate.timeIntervalSinceNow;
        if (timeToWaitForNextUpdate > 0)
        {
            // Start ignoring calls
            _updateScheduled = YES;
            dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(timeToWaitForNextUpdate * NSEC_PER_SEC)), _consoleQueue, ^
                           {
                               [self updateTableViewInConsoleQueue];

                               // Stop ignoring calls
                               _updateScheduled = NO;
                           });
        }
        else
        {
            [self updateTableViewInConsoleQueue];
        }
    });
}

- (void)updateTableViewInConsoleQueue
{
    _lastUpdate = NSDate.date;

    // ...
}

然而,我仍然不知道如何避免使用_minIntervalToUpdate,只是在表格视图准备就绪时更新"。