Вопрос

I'm trying to pace the update of a rapidly changing table view to display log messages by using performSelector:withObject:afterDelay::

  • The first new log message will schedule a table update after a minimum delay (0.5 seconds).
  • Successive log messages before that minimum delay should be ignored.
  • After updating the table view new updates can be scheduled again.

Similar questions "re-schedule" the original call by calling first cancelPreviousPerformRequestsWithTarget:.

Also I was wondering if:

  • GCD would be a better (which I'm sure would), and if it would be simpler (not sure).
  • Do I really need minimum refresh interval or is there a way to now if the table view is ready to update again (0.5 seconds may be unnecessary long or not enough depending on the device and its workload).

For people interested I'm refactoring this.

Это было полезно?

Решение

Well gave up on performSelector and came up with a GCD solution that is working pretty well:

Create a serial queue _consoleQueue = dispatch_queue_create("console_queue", NULL).

Message handling code where _updateScheduled works as a flag to ignore subsequent calls. The flag is only read and modified in the _consoleQueue to ensure consistency.

- (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;

    // ...
}

Yet I still don't know how to avoid using _minIntervalToUpdate and just update when the table view "is ready".

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top