代码之家  ›  专栏  ›  技术社区  ›  Septih

nsOutlineView未重新绘制

  •  0
  • Septih  · 技术社区  · 14 年前

    我有一个带有复选框的nsOutlineView。我将复选框状态绑定到具有shouldbecopied键的节点项。在节点项中,我有这样的getter和setter:

    -(BOOL)shouldBeCopied {
        if([[self parent] shouldBeCopied])
            return YES;
        return shouldBeCopied;
    }
    
    -(void)setShouldBeCopied:(BOOL)value {
        shouldBeCopied = value; 
        if(value && [[self children] count] > 0)
            [[self delegate] reloadData];
    }
    

    这里的想法是,如果检查了父级,那么子级也应该检查。我遇到的问题是,当我检查父对象时,如果子对象的视图已经展开,它不会更新这些子对象的视图。我可以理解,它不应该被绑定更新,因为我实际上并没有更改值。但是,ReloadData不应导致绑定重新获取值,因此调用 -shouldBeCopied 为了孩子们?我还试过其他一些东西,比如 -setNeedsDisplay -reloadItem:nil reloadChildren:YES 但没用。我注意到,当我切换到Xcode,然后再切换回来时,显示器会刷新,这就是我想要的,那么我该如何让它以这种方式工作呢?

    2 回复  |  直到 14 年前
        1
  •  1
  •   Peter Hosey    14 年前

    我有一个带有复选框的nsOutlineView。我将复选框状态绑定到具有shouldbecopied键的节点项。

    您是绑定列还是绑定单元格?您应该绑定列。

    -(BOOL)shouldBeCopied {
        if([[self parent] shouldBeCopied])
            return YES;
        return shouldBeCopied;
    }
    

    先利用孩子的价值不是更好吗?如果没有其他信息,检索起来会更便宜(不需要消息)。

    修正后的getter将如下所示:

    - (BOOL) shouldBeCopied {
         return (shouldBeCopied || [[self parent] shouldBeCopied]);
    }
    

    我遇到的问题是,当我检查父对象时,如果子对象的视图已经展开,它不会更新这些子对象的视图。

    有两种解决方案。一个比较干净,10点5分以后开始工作。另一个有点脏,可以在任何版本的MacOSX上使用。

    脏的解决方案是让setter方法中的父级代表其所有子级发布kvo通知。比如:

    [children performSelector:@selector(willChangeValueForKey:) withObject:@"shouldBeCopied"];
    //Actually change the value here.
    [children performSelector:@selector(didChangeValueForKey:) withObject:@"shouldBeCopied"];
    

    这是脏的,因为它有一个对象发布关于另一个对象属性的kvo通知。每个对象只应声称知道自己属性的值;声称知道另一个对象属性值的对象可能出错,导致错误和/或效率低下的行为,更不用说代码容易引起头痛。

    更清洁的解决方案是让每个对象观察其父对象的这个属性。通过 the NSKeyValueObservingOptionPrior option 将自己添加为观察员以便在更改之前收到通知(您将在 the observation method ,通过发送 [self willChangeValueForKey:] )以及更改后的通知(在观察方法中,您将通过发送 [self didChangeValueForKey:] )

    使用clean解决方案,每个对象只发送关于其自身属性更改的kvo通知;没有对象发布关于其他对象属性的通知。

    当属性的值为 YES 因为在这种情况下,父母的价值并不重要。不过,您不应该这样做,因为这只对儿童有效;如果更远的后代将属性设置为 NO ,那么该对象的祖先值毕竟很重要,并且只有当它的每个祖先都发布它时,该对象才会收到通知。

        2
  •  1
  •   Joshua Nozzi    14 年前

    您的setter不发送-willChangeValueForkey:和-didChangeValueForkey:更改前后,因此绑定机制不会“注意”更改。

    还有,告诉一个观点 任何东西 直接从模型对象…不是个好办法。在这种情况下,由于您使用的是绑定,因此树控制器应该注意更改(一旦您修复了setter以发送正确的通知),并更新大纲视图。