Валентин Сильванский (v_silvansky) wrote,
Валентин Сильванский
v_silvansky

NSTableView reloadData

Всем известно, что метод reloadData у NSTableView асинхронный. То есть, после его вызова в бэкграунде начинается перезагрузка данных, а сам метод возвращает управление немедленно.

Но иногда возникает задача узнать об окончании перезагрузки данных, но у делегата такого метода нет. На помощь приходит GCD:


- (void)reloadTable
{
    [self.tableView reloadData];
    dispatch_async(dispatch_get_current_queue(), ^{
        [self tableReloaded];
    });
}


Почему так? Метод reloadData начинает свою асинхронную работу в текущей очереди, как показывает дебаггер. А мы ставим в конец очереди наш блок.

Стоит ли полагаться на такое поведение? Пока это работает, но внутренняя реализация reloadData может поменяться уже в следующей версии SDK, к примеру, она может разбивать перезагрузку на части и каждую часть запускать только по окончанию предыдущей. Разумеется, нельзя сказать наверняка. Но пока это работает.

За исследования спасибо Саше Чёрному.

UPD: Провёл более подробные исследования. После вызова reloadData, таблица вызывает _tileAndRedisplayAll, который вызывает setNeedsDisplay: и _setTrackingAreasDirty:, а setNeedsDisplay:, разумеется, ставит редисплей в main queue. Так оно всё и работает. Единственный метод data source, который вызывается сразу, это numberOfRowsInTableView:, остальное вызывается по мере надобности. То есть, tableView:viewForTableColumn:row: будет вызыван из такой цепочки: layoutSubtreeIfNeeded -> layout -> updateVisibleRowViews -> ... -> _addViewToRowView:atColumn:row:.

Собственно, это можно считать доказательством вышеутверждённого.

UPD 2: Немного не связно написал первый UPD. Надо будет расписать всё подробно.
Subscribe
  • Post a new comment

    Error

    default userpic

    Your IP address will be recorded 

    When you submit the form an invisible reCAPTCHA check will be performed.
    You must follow the Privacy Policy and Google Terms of use.
  • 0 comments