3

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

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

我正在添加单元格

[self.tableView insertRowsAtIndexes:[NSIndexSet indexSetWithIndex:0] withAnimation:NSTableViewAnimationSlideDown];

并更新面板的高度:

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

(都在同一个 addRow 方法中)

这工作正常,但看起来很难看 - 表格视图和窗口彼此分开动画。我想要的只是同步它们,在 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.sizekeypath 会导致同样的异常。使用只frame返回不回调。

将感谢任何导致我在 KVO 中出现错误或使用窗口调整大小功能实现 tableview 的其他想法。

4

2 回答 2

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)

于 2013-03-06T08:17:47.513 回答
2
  1. bounds 和 frame 是 C 类型的结构,而不是对象。
  2. 尽管 Cocoa 会自动用 NSValue 包裹 bounds 和 frame,但 NSRect 不会包裹 NSSize。
  3. 更改通知将由 setXXX 函数触发。尝试添加一个按钮,并编写如下操作:

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

于 2013-03-06T08:01:08.157 回答