?

Log in

NSTableView reloadData - ещё о [entries|archive|friends|userinfo]
Валентин Сильванский

[ website | аккорды АукцЫона ]
[ userinfo | livejournal userinfo ]
[ archive | journal archive ]

NSTableView reloadData [Sep. 3rd, 2013|04:20 pm]
Валентин Сильванский
Всем известно, что метод 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. Надо будет расписать всё подробно.
LinkReply