【问题标题】:NSOutlineView : Expand all objects of a specific class onlyNSOutlineView : 仅展开特定类的所有对象
【发布时间】:2015-09-27 22:18:27
【问题描述】:

NSOutlineView 中扩展特定类的所有对象的最有效方法是什么? (我的大纲视图的数据源是NSTreeController)。

假设我有

classA
classA
    - classA
        - classC
        - classC
    - classB
        - classC
        - classC
classB
   - classC

我只想扩展 classA 对象。我是否需要遍历整个树来检查每个对象属于哪个类?

更新 对不起,我必须更正。 outlineView 对象是来自 NSTreeController 数据源的 NSTreeNodes。只有“representedObject”是我的自定义类。

所以这些类的结构是正确的,但它们不能作为大纲视图的节点直接访问。

【问题讨论】:

    标签: objective-c macos cocoa


    【解决方案1】:

    我是否需要遍历整个树来检查每个对象属于哪个类?

    是的,因为那是你想要做的。

    但这并不像stevesliva的A那么容易:

    A.您不应该遍历大纲视图的项目。这是一个视图。它与数据无关。即,如果一个节点是关闭的,则后代在行列表中是 not。这是因为它们没有行。

    B.而是迭代树控制器的内容。控制器是为数据访问而设计的,因此它是访问数据的正确位置。 -arrangedObjects (NSTreeController) 让您可以访问内容。

    【讨论】:

    • 这就像 stevesilva 的回答一样简单,因为没有迹象表明 OP 想要扩展 包含 classA 对象的节点,只是扩展那些 classA 对象。如果classA 对象位于折叠的classB 对象内部,则该classA 对象是“展开”还是“折叠”都没有关系。那没有什么特别的意义。因此,遍历行并扩展您遇到的classA 就足够了。
    • 有一个指示:“展开特定类的所有个对象”。除此之外,如前所述询问数据视图是一种有条不紊的错误方法。
    • @AminNegm-Awad - 如果您认为在尝试有效地修改视图而不是模型时无法查询视图,我认为您不必要地给自己戴上手铐。这类似于声明您不能使用视图层次代码删除所有视图的子视图,这很荒谬。控制器对其视图出口的所有权显式较弱,因为视图拥有视图层次结构的所有权,并且当您更改显示的内容时,您肯定可以遍历视图层次结构。
    • 视图的变化取决于模型中的数据,这里是数据的类型。所以你必须问模型。您可以通过控制器执行此操作。这是非常简单的MVC。删除视图中的子视图不依赖于模型中的数据。您可以在视图层中执行此操作。所以你可以去任何你想去的地方,但是如果你需要[underlyingData somewhat]你就得问控制器了。 (您可以使用 cocoa 绑定从视图中执行此操作,但这有点无用。)如前所述,如果您必须检查实际未显示的数据,您的方法至少会失败。
    • @AminNegm-Awad - 此代码将在在控制器中,至少任何类实现了大纲视图的委托方法。你可以同时拥有 一个 treeController,你知道的。我并不是建议将提供的代码 sn-p 包含在大纲视图的子类中,因为是的,将视图子类化以检查 isKindOfClass... 很丑...但它是 标准 用于实现 NSOutlineViewDelegate 的类来查询视图的状态和询问模型对象。
    【解决方案2】:

    听起来像是 NSOutlineViewDelegate 的工作:

    - (void)outlineView:(NSOutlineView *)outlineView willDisplayCell:(id)cell forTableColumn:(NSTableColumn *)tableColumn item:(id)item
    {
        if ([[item representedObject] isMemberOfClass:[ClassA class]]) {
            [outlineView expandItem:item];
        }
    }
    

    【讨论】:

      【解决方案3】:

      对于它的价值,我在评论中提到的重要“粘合剂”或多或少直接来自这篇很棒的博客文章:Saving the expand state of a NSOutlineView

      我获取了树中的所有类,并将它们设为具有expanded 属性的抽象类的子类,因此NSTreeNode 中的每个representedObject 都具有expanded 作为属性。

      但如果您不关心在数据模型中持久化expanded,您甚至可能不需要这样做。

      最简单的做法是迭代行:

          for (NSUInteger row = 0; row < [outlineView numberOfRows]; row++)
          {
              // Expand item if it's an classA
              NSTreeNode* treeNode = [outlineView itemAtRow:row];
              if ([treeNode.representedObject isKindOfClass:[ClassA class]])
                  [sender.animator expandItem:treeNode];
          }
      

      ...您会注意到 for 循环从引用的博客文章中借用了很多结构。

      所以我想我的回答是懒惰的,“是的,迭代整个树。”至少显示的树。

      编辑: 对于那些对 MVC 有点过分热心的人,我现在觉得有必要指定上面的代码应该在您用作 NSOutlineView 控制器的类中,这通常会实现&lt;NSOutlineViewDelegate&gt;

      【讨论】:

      • 对不起,我必须更正一下。 outlineView 对象是来自 NSTreeController 数据源的 NSTreeNodes。只有“representedObject”是我的自定义类。所以我不能为这些对象添加任何属性,因为我没有子类化节点。
      • @Patrick - 只是迭代行是简单的事情,所以你应该指定 O(rows) 的赏金不会削减它。我仍然认为 NSTreeNode 包装器对于上述情况来说并不是什么大问题,但我不得不眯着眼睛看我的旧代码以获得胶水。
      • @stevesliva 不幸的是,链接现在已损坏
      猜你喜欢
      • 2010-10-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-10-25
      • 2018-10-08
      相关资源
      最近更新 更多