如何在reloadData之后立即重新绘制NSTableView

时间:2012-02-21 19:12:30

标签: objective-c cocoa nstableview

我添加了NSTableView并正确设置了委托和数据源。

- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
    _items = [[NSMutableArray alloc] init];
    [_items addObject:@"ready"];
    [self.mainTableView reloadData];
}

- (NSInteger)numberOfRowsInTableView:(NSTableView *)tableView {
    return [self.items count];
}

- (NSView *)tableView:(NSTableView *)tableView viewForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row {
    NSTableCellView *result = [tableView makeViewWithIdentifier:tableColumn.identifier owner:self];
    result.textField.stringValue = [self.items objectAtIndex:row];
    return result;
}

还有一个NSButton与以下代码连接:

- (IBAction)buttonPressed:(id)sender {
    for (int i = 1; i <= 10; i++) {
        NSString *item = [NSString stringWithFormat:@"%d", i];
        [_items replaceObjectAtIndex:0 withObject:item];
        [self.mainTableView reloadData];
        [NSThread sleepForTimeInterval:0.2f];
    }
}

程序正确运行并在表格视图中显示“就绪”,但是当我单击按钮时,表格视图的内容没有立即更改。它在2秒后改变,只显示最后一个数字--10。

我想要的是将NSTableViw的内容从1更改为10但不直接获取最终数字。如何在reloadData之后立即重新绘制它?

2 个答案:

答案 0 :(得分:3)

[NSThread sleepForTimeInterval:0.2f];

你正在睡觉,并想知道为什么事情似乎被推迟了?!

[_items replaceObjectAtIndex:0 withObject:item];

您正在替换数组中的每个项目并想知道为什么只显示最后一项?!

你根本不应该睡觉主线程。删除该行;发送reloadData会使表格视图尽快重新显示。

要填充数组,请执行以下操作:

for (int i = 1; i <= 10; i++) {
    NSString *item = [NSString stringWithFormat:@"%d", i];
    [_items addObject:item];
}
[self.mainTableView reloadData];

请注意,我已将reloadData 移到了之外的循环中。在完成数据更新并准备好重新绘制表视图之前,不应发送它。

答案 1 :(得分:2)

  

如何在reloadData之后立即重新绘制它?

reloadData之后返回。没有其他办法。在代码仍在运行时,不能使表视图重绘。即使你使用了另一个线程,它也不会像你想象的那样工作。

如果您想要随时修改表格,可以使用NSTimer定期修改数据,然后在每次更改后调用reloadData(或者更好,reloadRowsAtIndexPaths:withRowAnimation:

用户界面永远不会在代码中间绘制。你必须返回让它更新。


当您的代码在主线程上运行时,UI无法更新。在处理过程中有几种方法可以提供UI更新:

  • 做一些工作,安排用计时器或performSelector:withObject:afterDelay:做更多工作,返回以便UI可以更新。这就是我上面所描述的。
  • 将您的工作分成小单位,并使用NSOperationQueue或GCD队列安排它们。如果在主队列上运行它们,这实际上与第一个选项相同;你只是让操作系统进行安排。
  • 在后台线程上运行处理并异步更新数据。使用计时器定期更新UI。这对于简单的进度表很有用,但如果您希望UI更新位于特定点,则很难同步。这引入了多线程代码的所有令人头疼的问题,例如锁定和原子。