【问题标题】:Get document object with current focus from NSCollectionView从 NSCollectionView 获取当前焦点的文档对象
【发布时间】:2016-08-04 18:13:07
【问题描述】:

我有一个(子类)NSCollectionView 打开,包含多个文本视图。每个文本视图都映射到一个(子类)NSDocument 对象。 (这个想法是使用文档架构的保存功能而不是它的窗口功能,因为我需要在同一个窗口中有多个文档,而传统的文档架构不允许这样做。)

现在,我希望用户能够从主菜单调用一个功能,该功能将影响他们当前选择的文档。即:该文档当前在具有当前焦点的文本视图中可见,并且菜单命令应该对该文档进行更改。但是菜单命令的发送者只是菜单。当窗口控制器处理来自菜单的命令时,如何告诉它当前选择的文档是什么?

【问题讨论】:

    标签: swift macos cocoa nstextview nscollectionview


    【解决方案1】:

    这就是the responder chain 的用途。

    由于您使用的是NSCollectionView,您可能已经有了NSCollectionViewItem 的子类。如果没有,请创建一个。在这个子类中实现您的操作方法。示例:

    class DocumentItem: NSCollectionViewItem {
    
        var document: MyDocument? {
            return representedObject as? MyDocument
        }
    
        @IBAction func doThatThing(sender: AnyObject?) {
            Swift.print("This is where I do that thing to \(document)")
        }
    
        // @IBOutlets and whatnot here...
    
    }
    

    您可能需要在 xib 或情节提要中将其设置为 NSCollectionViewItem 的自定义类。

    接下来,如果您的单元格视图(您的NSCollectionViewItem 拥有的视图)不是NSView 的自定义子类,您应该将其设为自定义子类。您必须覆盖 acceptsFirstResponder 才能返回 true:

    class DocumentCellView: NSView {
    
        override var acceptsFirstResponder: Bool { return true }
    
        // @IBOutlets and whatnot here...
    
    }
    

    确保将其设置为故事板或 xib 中单元格视图的自定义类。

    最后,将菜单项的操作连接到 First Responder 上的doThatThing:

    它是这样工作的:

    因为acceptsFirstResponder 的单元格视图现在返回true,所以当用户单击集合视图中的单元格视图时,系统会将其设为第一响应者(响应者链的开始) .

    当视图具有视图控制器时,它会使该视图控制器成为响应器链中的下一个响应器(如果您使用的是 OS X 10.10 Yosemite 或更高版本)。您的单元格视图有一个视图控制器:您从outlineView:itemForRepresentedObjectAtIndexPath: 返回的项目对象。 (NSCollectionViewItemNSViewController 的子类,因此您的自定义项是视图控制器。)

    当用户单击菜单项时,菜单项要求NSApplication 沿着响应者链发送其操作,从第一个响应者开始。第一个响应者是单元格视图,但它不响应 doThatThing: 消息。所以NSApplication 向视图询问其nextResponder,它是您的NSCollectionViewItem 子类的一个实例。该对象确实响应doThatThing:,因此NSApplicationdoThatThing: 发送到您的项目对象(使用NSMenuItem 对象作为sender 参数)并且不检查其余部分响应者链。

    【讨论】:

    • 太棒了!做得好!就我而言,答案实际上更简单。 NSTextViews 已经设置为接受 First Responder,所以我不需要对它们进行子类化。我只需要在我的 CollectionViewItem 子类中创建 @IBAction 并将菜单项连接到 First Responder 上。但我自己不会想到这一点。主要的道具不仅是想出一个对我很有效的简单答案,而且发布它的更复杂的变体,这将使这个问题的未来读者受益。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-06-26
    • 2018-11-14
    • 1970-01-01
    相关资源
    最近更新 更多