使用Cocoa绑定的类似iTunes的计数按钮

时间:2014-06-28 05:35:14

标签: macos cocoa itunes cocoa-bindings nsoutlineview

我想在侧边栏中显示一些项目,同时还会显示每个标记的计数:

enter image description here

如何有效且自动地执行此操作?简单的选择是使用cocoa绑定,但我不确定最好的方法是什么:每个按钮是否需要它自己的NSArrayController,并为'tag'设置一个fetch谓词?这可能最终会产生X个NSArrayControllers(每个标签一个),这将是相当重的(我想)。

另一个选项是手动创建获取请求,然后重新获取托管对象上下文中的每个更改。但这似乎有点混乱,而不是自动化。

这有更简单的解决方案吗?我用Google搜索并没有找到任何东西。

1 个答案:

答案 0 :(得分:1)

让我们假设您的NSOutlineView中有一个children" children"并且子节点具有布尔isNew属性。你想要的是一个对象类的单元格视图中的一个很好的numberOfNewItems气泡。我称之为父对象。

如果您只想要childrenKeyPath中的对象数量,那就更容易了,但是我将带您了解跟踪子项上特定布尔属性的更复杂情况,因为它&# 39;很容易简化这种模式。

在父对象的表格单元格视图中,添加一个隐藏式按钮,其中标题绑定到objectValue.numberOfNewItems并且隐藏绑定使用值变换器NSNegateBoolean到objectValue.NumberOfNewItems。如果您只想要孩子的数量,请将这些关键路径转换为objectValue.children.count,然后您就完成了。如果您想跟踪像isNew这样的房产,请继续......

在父对象类中,有以下代码:

- (NSNumber*) numberOfNewItems
{
     // Collection operator on boolean returns total number of new children
     return [self valueForKeyPath:@"children.@sum.isNew"];
}

// This setter does nothing, but with KVO it causes bindings 
//  to numberOfNewItems to call the above getter
- (void) setNumberOfNewItems:(NSNumber*)number { }

//  This ensures that changes to the children set causes KVO calls to the above getter
+ (NSSet*) keyPathsForValuesAffectingNumberOfNewItems
{
    return [[NSSet alloc] initWithObjects:@"children", nil];
}

这样做的原因是,只要表格单元格的objectValue将新子项添加到numberOfNewItems到多个关系中,就会重新计算children

在childItem类中,在一个地方将childItem从isNew转换为not-new:

// If collapsing an item, mark it as not new
if (!isExpanded.boolValue && self.isNewValue) {
    self.isNew = @NO;
    [self.parent setNumberOfNewItems:nil]; // Triggers KVO for button binding
}

... 所做的使用父空的setNumberOfNewItems setter来强制按钮绑定来调用getter。因此,每次将项目标记为非新时,都会枚举整个to-many children关系。我认为可以改进,但我还没有玩过。

我利用了一个事实,即我的代码中只有一个地方标记了一个项目。如果您在子项中重置或设置了isNew,可以覆盖childItem类中的setIsNew来调用self.parent setNumberOfNewItems:nil

这里的诀窍是让父母将自己添加为所有孩子的isNew keypath的KVO观察者将是一个可怕的痛苦。所以我想避免这种情况。如果您只是让孩子在父母中调用空的setter,父母可以拥有计算,并且在绑定使用的范围之外没有KVO。

看起来像这样:

enter image description here