I'm trying to pace the update of a rapidly changing table view to display log messages by using performSelector:withObject:afterDelay:
:
Similar questions "re-schedule" the original call by calling first cancelPreviousPerformRequestsWithTarget:
.
Also I was wondering if:
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".