У меня есть NSOutlineView, который использует собственный подкласс NSCell для рисования NSProgressIndicator.Каждый NSCell имеет свойство refreshing
, которое устанавливается методом делегата NSOutlineView willDisplayCell:forItem:
, например:
- (void)outlineView:(NSOutlineView *)outlineView willDisplayCell:(id)cell forTableColumn:(NSTableColumn *)tableColumn item:(id)item
{
cell.refreshing = item.refreshing;
}
Каждый экземпляр элемента содержит NSProgressIndicator, который запускается и останавливается в зависимости от того, является ли этот конкретный элемент
- (NSProgressIndicator *)startProgressIndicator
{
if(!self.progressIndicator)
{
self.progressIndicator = [[[NSProgressIndicator alloc] initWithFrame:NSMakeRect(0, 0, 16.0f, 16.0f)] autorelease];
[self.progressIndicator setControlSize:NSSmallControlSize];
[self.progressIndicator setStyle:NSProgressIndicatorSpinningStyle];
[self.progressIndicator setDisplayedWhenStopped:YES];
[self.progressIndicator setUsesThreadedAnimation:YES];
[self.progressIndicator startAnimation:self];
}
return self.progressIndicator;
}
- (void)stopProgressIndicator
{
if(self.progressIndicator != nil)
{
NSInteger row = [sourceList rowForItem:self];
[self.progressIndicator setDisplayedWhenStopped:NO];
[self.progressIndicator stopAnimation:self];
[[self.progressIndicator superview] setNeedsDisplayInRect:[sourceList rectOfRow:row]];
[self.progressIndicator removeFromSuperviewWithoutNeedingDisplay];
self.progressIndicator = nil;
}
for(ProjectListItem *node in self.children)
{
[node stopProgressIndicator];
}
}
Элементы экземпляров NSProgressIndicator останавливаются и запускаются в классе drawInteriorWithFrame:inView:
моего NSCell, например:
- (void)drawInteriorWithFrame:(NSRect)cellFrame inView:(NSView *)controlView
{
if(self.refreshing)
{
NSProgressIndicator *progressIndicator = [item progressIndicator];
if (!progressIndicator)
{
progressIndicator = [item startProgressIndicator];
}
// Set the progress indicators frame here ...
if ([progressIndicator superview] != controlView)
[controlView addSubview:progressIndicator];
if (!NSEqualRects([progressIndicator frame], progressIndicatorFrame)) {
[progressIndicator setFrame:progressIndicatorFrame];
}
}
else
{
[item stopProgressIndicator];
}
[super drawInteriorWithFrame:cellFrame inView:controlView];
}
Проблема, с которой я столкнулся, заключается в том, что хотя NSProgressIndicatorsправильно сказано, чтобы остановить, вызовы stopProgressIndicator не имеют никакого эффекта.Вот код, который не запускает обновление рассматриваемой строки NSOutlineView.Я вручную проверил NSRect, возвращенный моим вызовом rectOfRow, и могу подтвердить, что значение верное.
[self.progressIndicator setDisplayedWhenStopped:NO];
[self.progressIndicator stopAnimation:self];
[[self.progressIndicator superview] setNeedsDisplayInRect:[sourceList rectOfRow:row]];
[self.progressIndicator removeFromSuperviewWithoutNeedingDisplay];
self.progressIndicator = nil;
Когда NSOutlineView завершает обновление всех своих элементов, он запускает вызов reloadData:
.Это единственное, что, по-видимому, надежно обновляет все рассматриваемые ячейки, в конечном итоге удаляя NSProgressIndicators.
Что я здесь не так делаю?