如何在启动时设置 NSTreeController 的默认选择?

发布于 2024-08-30 01:42:21 字数 2131 浏览 1 评论 0原文

背景

我在我的 Cocoa 应用程序中构建了一个源列表(类似于 iTunes 等)。

  • 我有一个带有 Value 的 NSOutlineView 绑定到arrangedObjects.name的列 NSTreeController 的关键路径。

  • NSTreeController 访问 Core 中的 JGSourceListNode 实体 数据存储。

  • 我有三个子类 JGSourceListNode - JGProjectNode, JGGroupNode 和 JGFolderNode。

  • 我已将 NSTreeController 上的 selectedIndexPaths 绑定到我的应用程序委托中名为 selectedIndexPaths 的 NSArray。

启动时,我搜索组节点,如果在核心数据存储中找不到它们,我将创建它们:

if ([allGroupNodes count] == 0) {
    JGGroupNode *rootTrainingNode = [JGGroupNode insertInManagedObjectContext:context];
    [rootTrainingNode setNodeName:@"TRAIN"];

    JGProjectNode *childUntrainedNode = [JGProjectNode insertInManagedObjectContext:context];
    [childUntrainedNode setParent:rootTrainingNode];
    [childUntrainedNode setNodeName:@"Untrained"];

    JGGroupNode *rootBrowsingNode = [JGGroupNode insertInManagedObjectContext:context];
    [rootBrowsingNode setNodeName:@"BROWSE"];

    JGFolderNode *childFolder = [JGFolderNode insertInManagedObjectContext:context];
    [childFolder setNodeName:@"Folder"];
    [childFolder setParent:rootBrowsingNode];

    [context save:nil];
}

我想要的

当我启动应用程序时,我希望扩展两个顶级组并“未经训练”突出显示,如下所示:

我的窗口 http://synapticmishap.co.uk/Window.jpeg

问题

我将以下代码放在应用程序委托的 applicationDidFinishLaunching: 方法中:

[sourceListOutlineView expandItem:[sourceListOutlineView itemAtRow:0]];
[sourceListOutlineView expandItem:[sourceListOutlineView itemAtRow:2]];
NSIndexPath *rootIndexPath = [NSIndexPath indexPathWithIndex:0];
NSIndexPath *childIndexPath = [rootIndexPath indexPathByAddingIndex:0];
[self setSelectedIndexPaths:[NSArray arrayWithObject:childIndexPath]];

但是大纲视图似乎还没有准备好,所以这段代码什么也不做。

理想情况下,最终我想保存用户所做的最后选择并在重新启动时恢复它。

问题

我确信可以使用一些疯狂的 KVO 来观察 NSTreeController 或 NSOutlineView 何时被填充,然后展开项目并更改选择,但这感觉很笨拙,太像解决方法了。

我该如何优雅地做到这一点?

The Background

I've built a source list (similar to iTunes et al.) in my Cocoa app.

  • I've got an NSOutlineView, with Value
    column bound to arrangedObjects.name
    key path of an NSTreeController.

  • The NSTreeController accesses
    JGSourceListNode entities in a Core
    Data store.

  • I have three subclasses of
    JGSourceListNode - JGProjectNode,
    JGGroupNode and JGFolderNode.

  • I have selectedIndexPaths on NSTreeController bound to an NSArray called selectedIndexPaths in my App Delegate.

On startup, I search for group nodes and if they're not found in the core data store I create them:

if ([allGroupNodes count] == 0) {
    JGGroupNode *rootTrainingNode = [JGGroupNode insertInManagedObjectContext:context];
    [rootTrainingNode setNodeName:@"TRAIN"];

    JGProjectNode *childUntrainedNode = [JGProjectNode insertInManagedObjectContext:context];
    [childUntrainedNode setParent:rootTrainingNode];
    [childUntrainedNode setNodeName:@"Untrained"];

    JGGroupNode *rootBrowsingNode = [JGGroupNode insertInManagedObjectContext:context];
    [rootBrowsingNode setNodeName:@"BROWSE"];

    JGFolderNode *childFolder = [JGFolderNode insertInManagedObjectContext:context];
    [childFolder setNodeName:@"Folder"];
    [childFolder setParent:rootBrowsingNode];

    [context save:nil];
}

What I Want

When I start the app, I want both top level groups to be expanded and "Untrained" to be highlighted as shown:

My Window http://synapticmishap.co.uk/Window.jpeg

The Problem

I put the following code in the applicationDidFinishLaunching: method of the app delegate:

[sourceListOutlineView expandItem:[sourceListOutlineView itemAtRow:0]];
[sourceListOutlineView expandItem:[sourceListOutlineView itemAtRow:2]];
NSIndexPath *rootIndexPath = [NSIndexPath indexPathWithIndex:0];
NSIndexPath *childIndexPath = [rootIndexPath indexPathByAddingIndex:0];
[self setSelectedIndexPaths:[NSArray arrayWithObject:childIndexPath]];

but the outline view seems to not have been prepared yet, so this code does nothing.

Ideally, eventually I want to save the last selection the user had made and restore this on a restart.

The Question

I'm sure it's possible using some crazy KVO to observe when the NSTreeController or NSOutlineView gets populated then expand the items and change the selection, but that feels clumsy and too much like a work around.

How would I do this elegantly?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

郁金香雨 2024-09-06 01:42:21

优雅?这并不优雅,但我就是这样做的。我只是手动完成。在应用程序退出时,我将此值写入用户默认值:

lastSelectedRow = [outlineView selectedRow]

然后在应用程序启动时,我在应用程序中运行此值并完成启动:

[self performSelector:@selector(selectLastNoteOrCreateDefaultNote) withObject:nil afterDelay:1];

注意我只是使用延迟,因为我注意到与您相同的“大纲视图似乎尚未准备好” 。然后在该选择器中我使用它。

[outlineView selectRowIndexes:[NSIndexSet indexSetWithIndex:lastSelectedRow] byExtendingSelection:NO];

它有效,但我也欢迎更好(更优雅)的解决方案。

Elegantly? This isn't elegant but it's how I'm doing it. I just do it manually. At app quit I write this value to user defaults:

lastSelectedRow = [outlineView selectedRow]

Then at app launch I run this in app did finish launching:

[self performSelector:@selector(selectLastNoteOrCreateDefaultNote) withObject:nil afterDelay:1];

Notice I just use a delay because I noticed the same as you that "the outline view seems to not have been prepared yet". Then in that selector I use this.

[outlineView selectRowIndexes:[NSIndexSet indexSetWithIndex:lastSelectedRow] byExtendingSelection:NO];

It works but better (more elegant) solutions are welcome from me too.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文