保持NSScrollView固定

时间:2012-09-06 08:20:57

标签: cocoa nstableview nsscrollview

我在NSScrollView中有一个NSTableView。 NSTableView的内容是通过绑定到绑定到CoreData ManagedObjectContext的NSArrayController提供的。 NSTableView的新行只是添加,并且从未删除或重新排序。

我想将NSTableView(或NSScrollView)固定在底部,以便添加到表中的新行立即可见。此外,当NSTableView滚动到底部而不是当用户向上滚动以查看其他行时,这将发生。

我目前正在使用以下代码

- (void)tableView:(NSTableView *)tableView didAddRowView:(NSTableRowView *)rowView forRow:(NSInteger)row {
    NSInteger numberOfRows = [tableView numberOfRows];
    NSLog(@"row: %lu, %lu numberOfRows ", row, numberOfRows);
    if (row == numberOfRows-1) {
        [tableView scrollRowToVisible:numberOfRows - 1];
    }
} 

到目前为止,这是有效的,但只是在窗口处于活动状态时。当窗口处于非活动状态时,在窗口再次变为活动状态之前,不会调用didAddRowView方法。因此,NSTableView不会立即向下滚动。由于NSTableView也通过CoreData绑定填充,我不知道在插入新项目后我可以手动触发滚动的任何一点。另外,didAddRowView委托方法经常被调用(例如,当手动滚动表时),并且只有在插入新项目时才真正需要向下滚动,这使得解决方案更不优雅。

是否可以在应用程序处于活动状态时直接挂钩到插入过程或NSScrollView以向下滚动到底部,在将新行添加到NSTableView时是否处于非活动状态?

修改 为了完成或者@rdelmar的解决方案不适合你,我已经将NSTableView子类化了,并在reloadData方法中实现了这个

- (void) reloadData {
    [super reloadData];
    NSInteger numberOfRows = [self numberOfRows];
    NSRange rowsInRect = [self rowsInRect:self.superview.bounds];
    NSInteger lastVisibleRow = rowsInRect.location + rowsInRect.length;

    if (lastVisibleRow == numberOfRows-1) {
        [self scrollRowToVisible:numberOfRows - 1];
    }
}

一旦在ArrayController中收到新项,就会调用reloadData方法,并将其添加到表中。在调用超类的reloadData之后,这将检查TableView是否滚动到底部(TableView的最后一行是superview中可见的最后一行 - 因此是周围的NSScrollView)。如果是这样,它会向下滚动。如果不是,则用户可能向上滚动以查看该表的某些内容并且不希望它自动向下滚动。

1 个答案:

答案 0 :(得分:0)

我认为您应该能够使用NSManagedObjectContext通知NSManagedObjectContextObjectsDidChangeNotification。创建一个自定义的NSTableView类并为该通知添加一个观察者:

@implementation CustomTable

-(void)awakeFromNib {
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(scrollTable:) name:NSManagedObjectContextObjectsDidChangeNotification object:nil];
}

-(void)scrollTable:(NSNotification *) aNote {
    if ([[aNote.userInfo allKeys] containsObject:@"inserted"]) {
        [self scrollRowToVisible:self.numberOfRows -1];
    }else{
        NSLog(@"It was not an insertion");
    }
}