无法获取 collection 视图的选定项目

Unable to get selected item of collection view

我在尝试使用 Xcode 6 选择我的 Collection 视图并尝试构建 OSX 应用程序时遇到问题。

我按照 http://developer.apple.com/mac/library/DOCUMENTATION/Cocoa/Conceptual/CollectionViews/Introduction/Introduction.html 中的说明创建了 collection 视图,它按预期工作,但我无法选择我单击的项目。我确保在 IB 中可以选择该视图。

我实现了 Selection Highlight in NSCollectionView 中提到的通知方法,当我填充 collection 视图时,我可以看到事件触发,但无论我在 collection 视图项中单击何处通知不会再次触发。

我认为 collection 视图是正常的,我只是想获取所选项目的数组索引,以便显示详细信息。

我浏览了网上的文章试图找到解决方案,但绝大多数解决方案都是针对 IOS 使用 segue 的,而不是针对 OSX。我为 Stack Overflow 发布的 link 例外。

我什至在我的整个 collection 视图项上放了一个透明按钮,这样我就可以抓住一个点击事件(这有效,但我仍然不知道点击了哪个项目)。

我的问题是:如何获取我在 collection 视图中单击的内容的数组项?

了解阵列控制器变化的一种方法 selectionIndexes 是将此 属性 绑定到代码中某处的 NSIndexSet 实例,然后使用 KVO 设计模式来当此 NSIndexSet 更改时请求通知。如果设置正确,当用户单击 NSCollectionView 中未选中的单元格时,数组控制器用于存储其选择索引的 NSIndexSet 将更新。由于此索引集是您正在观察的索引集,因此您会收到一条通知,告知您有关更改的信息。

在我为回答这个问题而创建的 demo-app 中,我将有问题的索引集放在 AppDelegate - 这是实现文件:

// Interface ////////////////////////////////////////////////////////

@interface AppDelegate ()

// This is the content array from which the NSArrayController will derive
// it's arrangedObjects array
@property (nonatomic, strong) NSArray *collectionViewContent;

// This is the NSIndexSet that I want the NSArrayController to use
// to store its selectionIndexes.
@property (nonatomic) NSIndexSet *mySelectionIndexes;

@end

// Implementation //////////////////////////////////////////////////

@implementation AppDelegate

- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {

    // The content that will be shown in the NSCollectionView (each word
    // represents a single collection view item).
    self.collectionViewContent = @[@"The", @"rain", @"in", @"Spain", @"falls", @"..."];

    // Tell cocoa you want to know when the array controller makes changes to
    // the index set it's using to stores its selection indexes
    [self addObserver:self
           forKeyPath:@"mySelectionIndexes"
              options:0
              context:nil];
}


-(void)observeValueForKeyPath:(NSString *)keyPath
                     ofObject:(id)object
                       change:(NSDictionary *)change
                      context:(void *)context {
    NSLog(@"Collection view selection just changed to: %@", self.mySelectionIndexes);
}

//////////////////////////////////////////////////////////////////

Bindings InspectorNSArrayController 您现在可以告诉阵列控制器使用 AppDelegate 属性 mySelectionIndexes 存储其选择索引:

如果您仍然遇到问题,可能是您在其他地方的绑定出错了 - 以下是我使用的所有绑定:

NSArrayController 数组控制器将从 AppDelegate 对象管理的数组中获取它的内容。它会将其选择索引存储在 NSIndexSet 中,也由 AppDelegate

管理
  1. 内容数组:应用Delegate.collectionViewContent
  2. 选择索引:应用Delegate.mySelectionIndexes

NSCollectionView 集合视图将从数组控制器获取它的模型数据。它将标记为 selected 那些出现在存储在数组控制器的索引中的视图 selectionIndexes 属性:

  1. 内容:数组Controller.arrangedObjects
  2. 选择索引:数组Controller.selectionIndexes

在我将 NSCollectionView 拖到 canvas 上时自动生成的视图上,我添加了一个 NSTextField,这个文本字段只有一个绑定:

  1. 值:集合视图 Item.representedObject(换句话说,将 representedObject 键入 模型键路径 字段。

最后一句话:

值得指出的是,您没有设置此绑定。要在用户选择或取消选择集合视图中的一项时获取信息,请创建 NSCollectionViewItem 的子类并覆盖 selected setter。每次选择或取消选择项目时都会自动调用此 属性。在您的实施中,您现在可以调整项目的视图以考虑其状态已更改的事实。在我的 demo-app 中,我自定义的 NSCollectionViewItem 子类被称为 PPCollectionViewItem:

@implementation PPCollectionViewItem

-(void)setSelected:(BOOL)selected {
    // Call super...
    [super setSelected:selected];

    // ...now change the view associated with this item. Remember,
    // the view is one of the cells in the NSCollectionView - I
    // changed it from a standard NSView, to a subclass called
    // CollectionViewCell which keeps a flag indicating whether
    // or not it's selected (the drawRect routine is varied
    // according to this flag's value).
    [(CollectionViewCell *)self.view setDrawAsSelected:selected];
}

@end