在更改树中的节点后,将重新排列对象发送到 NSTreeController的适当方法是什么?我有一个示例应用程序(下面的完整代码),它使用 NSOutlineView 和 NSTreeController 以及一个简单的 Node 对象树。
在应用程序的版本 1 中,当您编辑节点的名称时,直到您单击列标题或使用菜单中的“重新排列”项,树才会重新排列。后者设置为直接将重新排列对象发送到 NSTreeController。
在版本 2 中,我尝试从节点的 setName: 方法发送重新排列对象。这似乎不是一个好的解决方案,因为这意味着模型现在已经了解了视图/控制器。此外,它的副作用是大纲视图在重命名后失去焦点(如果您选择一个节点并编辑其名称,选择栏会从蓝色变为灰色)出于某种原因(为什么会这样?)。
NSArrayController 有一个方法setAutomaticallyRearrangesObjects:但是 NSTreeController 没有?那么解决这个问题的适当方法是什么?
/* example.m
Compile version 1:
gcc -framework Cocoa -o Version1 example.m
Compile version 2:
gcc -framework Cocoa -o Version2 -D REARRANGE_FROM_SETNAME example.m
*/
#import <Cocoa/Cocoa.h>
NSTreeController *treeController;
NSOutlineView *outlineView;
NSScrollView *scrollView;
@interface Node : NSObject {
NSString *name;
NSArray *children;
}
@end
@implementation Node
- (id) initWithName: (NSString*) theName children: (id) theChildren
{
if (self = [super init]) {
name = [theName retain];
children = [theChildren retain];
}
return self;
}
- (void) setName: (NSString*) new
{
[name autorelease];
name = [new retain];
#ifdef REARRANGE_FROM_SETNAME
[treeController rearrangeObjects];
#endif
}
@end
NSArray *createSortDescriptors()
{
return [NSArray arrayWithObject: [NSSortDescriptor sortDescriptorWithKey:@"name" ascending:YES]];
}
void createTheTreeController()
{
Node *childNode1 = [[[Node alloc] initWithName:@"B" children:[NSArray array]] autorelease];
Node *childNode2 = [[[Node alloc] initWithName:@"C" children:[NSArray array]] autorelease];
Node *childNode3 = [[[Node alloc] initWithName:@"D" children:[NSArray array]] autorelease];
Node *topNode1 = [[[Node alloc] initWithName:@"A" children:[NSArray arrayWithObjects:childNode1,childNode2,childNode3,nil]] autorelease];
Node *topNode2 = [[[Node alloc] initWithName:@"E" children:[NSArray array]] autorelease];
Node *topNode3 = [[[Node alloc] initWithName:@"F" children:[NSArray array]] autorelease];
NSArray *topNodes = [NSArray arrayWithObjects:topNode1,topNode2,topNode3,nil];
treeController = [[[NSTreeController alloc] initWithContent:topNodes] autorelease];
[treeController setAvoidsEmptySelection:NO];
[treeController setChildrenKeyPath:@"children"];
[treeController setSortDescriptors:createSortDescriptors()];
}
void createTheOutlineView()
{
outlineView = [[[NSOutlineView alloc] initWithFrame:NSMakeRect(0, 0, 284, 200)] autorelease];
[outlineView bind:@"content" toObject:treeController withKeyPath:@"arrangedObjects" options:nil];
[outlineView bind:@"sortDescriptors" toObject:treeController withKeyPath:@"sortDescriptors" options:nil];
[outlineView bind:@"selectionIndexPaths" toObject:treeController withKeyPath:@"selectionIndexPaths" options:nil];
NSTableColumn *column = [[[NSTableColumn alloc] initWithIdentifier:@"NameColumn"] autorelease];
[[column headerCell] setStringValue:@"Name"];
[outlineView addTableColumn:column];
[outlineView setOutlineTableColumn:column];
[column bind:@"value" toObject:treeController withKeyPath:@"arrangedObjects.name" options:nil];
[column setWidth:250];
scrollView = [[[NSScrollView alloc] initWithFrame:NSMakeRect(0, 0, 300, 200)] autorelease];
[scrollView setDocumentView:outlineView];
[scrollView setHasVerticalScroller:YES];
}
void createTheWindow()
{
id window = [[[NSWindow alloc] initWithContentRect:NSMakeRect(0, 0, 300, 200)
styleMask:NSTitledWindowMask backing:NSBackingStoreBuffered defer:NO]
autorelease];
[window cascadeTopLeftFromPoint:NSMakePoint(20,20)];
[window setTitle:@"Window"];
[window makeKeyAndOrderFront:nil];
[[window contentView] addSubview:scrollView];
}
void createTheMenuBar()
{
id menubar = [[NSMenu new] autorelease];
id appMenuItem = [[NSMenuItem new] autorelease];
[menubar addItem:appMenuItem];
[NSApp setMainMenu:menubar];
id appMenu = [[NSMenu new] autorelease];
#ifndef REARRANGE_FROM_SETNAME
id rearrangeMenuItem = [[[NSMenuItem alloc] initWithTitle:@"Rearrange"
action:@selector(rearrangeObjects) keyEquivalent:@"r"] autorelease];
[rearrangeMenuItem setTarget: treeController];
[appMenu addItem:rearrangeMenuItem];
#endif
id quitMenuItem = [[[NSMenuItem alloc] initWithTitle:@"Quit"
action:@selector(terminate:) keyEquivalent:@"q"] autorelease];
[appMenu addItem:quitMenuItem];
[appMenuItem setSubmenu:appMenu];
}
void setUpAutoReleasePoolAndApplication()
{
[NSAutoreleasePool new];
[NSApplication sharedApplication];
[NSApp setActivationPolicy:NSApplicationActivationPolicyRegular];
}
void activateAppAndRun()
{
[NSApp activateIgnoringOtherApps:YES];
[NSApp run];
}
int main(int argc, const char * argv[])
{
setUpAutoReleasePoolAndApplication();
createTheTreeController();
createTheOutlineView();
createTheWindow();
createTheMenuBar();
activateAppAndRun();
return 0;
}