Apple SidebarDemo的奇怪行为

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

标签: macos cocoa nsoutlineview reloaddata

我必须在我的Mac应用程序中添加一个源列表(例如iTunes)。为此,我尝试了(SidebarDemo from Apple)。它工作正常。我在此演示中添加了一个按钮,以演示reloadData方法对NSOutlineView的影响。正如您在图片中看到的那样,存在问题(左侧,reloadData呼叫前,右侧,reloadData呼叫后)。徽章消失,图标改变等等。

有什么问题?我应该避免在reloadData上使用NSOutlineView吗?

我正在使用OS X 10.8.2,SDK 10.8和Xcode 4.5.2。

您可以下载修改后的SidebareDemo项目here

谢谢!

Before and after...

1 个答案:

答案 0 :(得分:1)

SidebarDemo示例代码错误地使用相同的对象来表示大纲视图中的多行。特别是,数据源使用的基础数据的创建方式如下:

_childrenDictionary = [NSMutableDictionary new];
[_childrenDictionary setObject:[NSArray arrayWithObjects:@"ContentView1", @"ContentView2", @"ContentView3", nil] forKey:@"Favorites"];
[_childrenDictionary setObject:[NSArray arrayWithObjects:@"ContentView1", @"ContentView2", @"ContentView3", nil] forKey:@"Content Views"];
[_childrenDictionary setObject:[NSArray arrayWithObjects:@"ContentView2", nil] forKey:@"Mailboxes"];
[_childrenDictionary setObject:[NSArray arrayWithObjects:@"ContentView1", @"ContentView1", @"ContentView1", @"ContentView1", @"ContentView2", nil] forKey:@"A Fourth Group"];

编译器只提供具有相同值的NSString文字,因此每次出现@"ContentView1"都会引用内存中的同一对象。结果是,当-outlineView:viewForTableColumn:item:内的代码查找项的父级以确定要使用哪个图标或未读状态时,-[NSOutlineView parentForItem:]将只返回所有@"ContentView1"的单个父级。 1}}项目。在初始案例中它完全起作用的事实似乎是实施中的意外。在初始加载和重新加载期间,对-outlineView:viewForTableColumn:item:的调用的顺序略有不同。

解决方案是使用唯一对象来表示大纲视图中的每个项目。对SidebarDemo示例进行的最简单的修改就是在将每个NSString值存储到_childrenDictionary之前创建一个可变副本:

_childrenDictionary = [NSMutableDictionary new];
[_childrenDictionary setObject:[NSArray arrayWithObjects:[@"ContentView1" mutableCopy], [@"ContentView2" mutableCopy], [@"ContentView3" mutableCopy], nil] forKey:@"Favorites"];
[_childrenDictionary setObject:[NSArray arrayWithObjects:[@"ContentView1" mutableCopy], [@"ContentView2" mutableCopy], [@"ContentView3" mutableCopy], nil] forKey:@"Content Views"];
[_childrenDictionary setObject:[NSArray arrayWithObjects:[@"ContentView2" mutableCopy], nil] forKey:@"Mailboxes"];
[_childrenDictionary setObject:[NSArray arrayWithObjects:[@"ContentView1" mutableCopy], [@"ContentView1" mutableCopy], [@"ContentView1" mutableCopy], [@"ContentView1" mutableCopy], [@"ContentView2" mutableCopy], nil] forKey:@"A Fourth Group"];

在实际代码中,您不太可能被此问题所困扰,因为您的基础数据对象将由模型类的实例组成,而不是仅由字符串文字组成。