NSTableView的documentView大小观察

时间:2013-03-01 20:14:57

标签: cocoa nstableview key-value-observing nsscrollview

我在菜单栏弹出窗口中插入NSTableView。

我想调整弹出窗口的面板以使tableview符合其内容。例如,如果没有行 - 隐藏了tableview。通过添加新行,我将根据当前tableview高度+新单元格的高度重新计算面板的高度。

我正在添加

的单元格
[self.tableView insertRowsAtIndexes:[NSIndexSet indexSetWithIndex:0] withAnimation:NSTableViewAnimationSlideDown];

并使用以下内容更新面板的高度

[[self window] setFrame:panelRect display:YES animate:YES];

(全部采用相同的addRow方法)

这工作正常,但看起来很丑 - tableview和window是相互分开的动画。我想要的只是同步它们,同时移动窗口的边框,同时使tableview增长和缩小。

根据我的iOS开发经验,我有一个想法 - 观察tableview的contentSize,但我没有采用这种方法:

- (void)awakeFromNib
{
    [super awakeFromNib];
    ...
    [self.scrollView.documentView addObserver:self forKeyPath:@"bounds.size" options:NSKeyValueObservingOptionNew context:NULL];
}

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
    NSLog(@"!");
}

self.scrollview链接到IB中的tableview的容器滚动视图。该代码导致异常:

An instance 0x10053a1d0 of class NSConcreteValue was deallocated while key value observers were still registered with it. Observation info was leaked, and may even become mistakenly attached to some other object. Set a breakpoint on NSKVODeallocateBreak to stop here in the debugger. Here's the current observation info:
<NSKeyValueObservationInfo 0x10053c850> (
<NSKeyValueObservance 0x10053c7a0: Observer: 0x10053a160, Key path: size, Options: <New: YES, Old: NO, Prior: NO> Context: 0x0, Property: 0x10053c880>
)

使用frame.size密钥路径导致相同的异常。仅使用frame不会返回回调。

非常感谢我在KVO中出现错误或者使用窗口调整大小功能实现tableview的其他想法。

2 个答案:

答案 0 :(得分:3)

可能无法通过动画解决您的问题。但是,在取消分配对象之前,应该从对象中删除观察者。这将使例外消失。即在这种情况下你应该

<德尔> [self.scrollView.documentView removeObserver:self forKeyPath:@"bounds.size"];

[self.scrollView.documentView removeObserver:self forKeyPath:@"frame"]

这应该在self.scrollView.documentView内存不足之前完成。 考虑到这可能很棘手,你可以尝试添加这样的观察者:

<德尔> [self addObserver:self forKeyPath:@"self.scrollView.documentView.bounds.size" options:NSKeyValueObservingOptionNew context:Nil];

[self addObserver:self forKeyPath:@"self.scrollView.documentView.frame" options:NSKeyValueObservingOptionNew context:Nil];

另一件事,我记得在某个地方阅读,观察框架或边界,通常不被认为是一个好主意,但我不确定这一点。

编辑:考虑其他答案:“bounds.size”将无效,因为size未直接使用任何setter方法设置。因此,请观察框架并从中提取尺寸信息。 (对于UIView,只有帧是可观察的而不是边界。我猜这同样适用于NSView)

答案 1 :(得分:2)

  1. bounds和frame是C类型结构,而不是对象。
  2. 虽然Cocoa自动包装了NSValue的边界和框架,但NSRect不会包装NSSize。
  3. 更改通知将由setXXX函数触发。尝试添加按钮,并按如下方式编写操作:

    [self.scrollView.documentView setBounds:NSMakeRect(0,0,100,100)];