NSOutlineView reloadItem: 没有效果

17

我正在尝试释放一个基于视图的NSOutlineView上的一些紧张情况。我更改了单个项目属性,并最初使用[myOutlineView reloadData]成功重新加载。

我尝试使用[myOutlineView reloadItem: myOutlineViewItem],但它从未调用- (NSView *)outlineView:(NSOutlineView *)ov viewForTableColumn:(NSTableColumn *)tableColumn item:(id)item方法,因此数据没有更新。

-(void)reloadOutlineViewObject
{
    //[myOutlineView reloadData];   //Reload data just fines but is ressource-hungry
    NSLog(@"%d",[myOutlineView rowForItem:myOutlineViewItem]; //Making sure my object is an item of the outlineView, which it is !
    [myOutlineView reloadItem:myOutlineViewItem];   
}

我在这里是否漏掉了什么?

更新

评论中指出,我的outlineView是基于视图的。

更新2

尝试了一些东西后,我意识到我重新加载的对象是第二级对象(参见对象树),调用reloadItem:firstLevelObject reloadChildren:YES 确实有效。

可能只能对一级对象调用reloadItem:吗? 在我的情况下这将非常低效(我只有一个双层项和大量的二级项)!

nil ->firstLevelA ->secondLevel1
                  ->secondLevel2
    ->firstLevelB ->secondLevel3
                  ->secondLevel4

我打算尝试子类化NSOutlineView,并在此期间重写reloadItem:

更新3

我查看了Cocotron中的NSOutlineView,并感觉需要编写的代码来覆盖 reloadItem 会相当繁重。有人可以确认吗?


这个表是基于视图的,不是基于单元格的,对吗? - JWWalker
确实如此。这有关紧要吗? - Bertrand Caron
1
我也遇到了这个问题。你找到任何解决方法了吗? - Anton
很遗憾,我没有。你觉得是否值得向苹果支持团队咨询一下? - Bertrand Caron
4个回答

16

我在使用基于视图的大纲视图时遇到了同样的问题,调用-reloadItem:似乎没有任何作用。虽然文档没有明确说明reloadItem会重新获取该行的视图,但这显然是一个重大的错误。

我的解决方法是调用NSTableView-reloadDataForRowIndexes:columnIndexes:,它似乎按预期工作,并触发一个仅针对该项目的-outlineView:viewForTableColumn:item:代理方法的调用。您可以通过调用-rowForItem:并传入要重新加载的项目来获取需要重新加载的行。


1
也刚刚尝试在项的父级上调用-reloadItem:reloadChildren:,只要为reloadChildren参数传递YES,似乎就可以工作。但是,这当然会重新加载所有子项,而不仅仅是一个项。 - Brian Webster
谢谢!正如你所想象的那样,我现在与项目有些不同步,可能需要一些时间来验证答案 ;) - Bertrand Caron
1
我在看到这个之后非常乐观,但不幸的是它对我也不起作用。 - greg
1
啊,方法名打错了:实际上是-reloadDataForRowIndexes:columnIndexes:。现在已经在答案中修正了。 - Brian Webster
对我来说,调用-reloadDataForRowIndexes:columnIndexes:可以很好地解决问题。对于那些感兴趣的人,我在2015年1月提交了一个错误报告。rdar://19370431 -- 这绝对是一个100%可重现的NSOutlineView错误,导致-reloadItem:要求其数据源为项目行准备单元格视图,使我们无法更新单元格视图中的新值。通过-reloadItem:item.parent reloadChildren:YES重新加载项目的父级也可以工作,但这忽略了只重新加载一个子项的要点(特别是如果父项是根)。 - Joshua Nozzi
显示剩余5条评论

11

这并不是一个bug - 这是我明确设计的东西。我的想法是reloadItem(等等)应该只重新加载大纲视图项属性,而不是该项的表格单元格,因为它没有足够的特定信息来确定要重新加载什么(例如您想要重新加载哪个特定单元格)。我原本打算让人们使用reloadDataForRowIndexes:columnIndexes:来重新加载基于视图的特定表格视图单元格; 当基类可以只用几行代码就能完成同样的事情时,我们通常不提供覆盖方法。

但是,话虽如此,我知道有多个人对此感到困惑,大多数人都希望也重新加载单元格。

请记录一个错误请求,要求苹果更改此内容。

谢谢, -corbin


4
苹果似乎已经“修复”了这个问题。在WWDC 2016的203演示“Cocoa的新功能”中,在视频的30:35处听到:“NSOutlineView会在调用reloadItem()时重新加载与‘item’相关联的单元格视图”。

2

reloadItem:仅适用于macOS 10.12。

从发行说明中可以看到: https://developer.apple.com/library/content/releasenotes/AppKit/RN-AppKit/

当调用[outlineView reloadItem:]时,NSOutlineView将重新加载与“item”相关联的单元格视图。该方法只是传递要重新加载的特定行和所有列的[outlineView reloadDataForRowIndexes:columnIndexes:]。为了兼容性,这仅适用于链接到10.12 SDK的应用程序。

因此,如果您想在早期系统上重新加载行,则应使用-reloadDataForRowIndexes:columnIndexes:。类似这样:

let index = outlineView.row(forItem: obj)
let rowIndex = IndexSet(integer: index)

let cols = IndexSet(0 ... outlineView.numberOfColumns) 

outlineView.reloadData(forRowIndexes: rowIndex, columnIndexes: cols)

1
多么可怕,但这是真的,因此MacOS部署目标决定了行为... - Hans

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接