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"
项。它在最初的情况下完全有效的事实似乎是实施中的意外。-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"];
在实际代码中,您不太可能被此问题困扰,因为您的底层数据对象将由模型类的实例组成,而不是仅由字符串文字组成。