【问题标题】:Cocoa: Avoiding 'Updates Continuously' in control bindsCocoa:在控制绑定中避免“不断更新”
【发布时间】:2012-03-30 22:41:24
【问题描述】:

我有几个面板包含NSTextField 控件绑定到文件的所有者 对象内的属性。如果用户编辑一个字段,然后按 Tab 键移动到下一个字段,它会按预期工作。但是,如果用户不按 Tab 并仅按 OK 按钮,则不会在 File's Owner 对象中设置新值。

为了解决这个问题,我在绑定中设置了 Updates Continuously,但这一定很昂贵(编辑:或者至少它不优雅)。

有没有办法在按下确定按钮时强制绑定更新,而不是使用持续更新

【问题讨论】:

  • 是什么让你觉得“持续更新”很贵?是吗?你有简介吗?
  • 嗯,不,像往常一样 Rob,但是它在我的核心 C++ 库中设置值,这涉及到 std::string 对象的构造和 NSString 对象之间的转换。这似乎不优雅,我认为必须有更好的方法。
  • 我同意,只是对性能做出假设从来都不是一个好主意。过早的优化是邪恶的!
  • 不是真的抢。当你编码的时间足够长时,你就会感觉到什么是正确的。 premature optimisation 参数是垃圾 - 第一次就可以有效地对其进行编码。对自己的工作感到满意很重要,而在不考虑性能的情况下编写代码只会让我不开心。
  • 我不同意这个论点是垃圾,我看到很多过于复杂、过度设计的代码用于解决现实中不存在的感知可能的性能问题。但是,我确实同意高效地编写代码会更好。在这种情况下,我认为优化它是正确的,它更优雅,但从性能的角度来看,它可能不会对最终用户产生太大影响。但是,由于我们正在迅速偏离主题,所以我将把它留在那里。

标签: cocoa binding key-value-observing nstextfield


【解决方案1】:

您是对的,您不需要使用持续更新值选项。

如果您正在使用绑定(您就是这样),那么您应该做的是调用管理绑定的NSController 子类的-commitEditing 方法。您通常会在关闭您正在显示的工作表的方法中执行此操作。

-commitEditing 告诉控制器在活动控件中完成编辑并将当前编辑提交到绑定对象。

在执行持久性操作(例如保存)时调用它是个好主意。

【讨论】:

  • 那么这是否意味着您需要为窗格中的每个控件提供一个出口,并且需要在关闭窗格之前对所有控件调用commitEditing?还是有更简单的方法来实现这一点?
  • 您不会在控件上调用commitEditing,而是在控件绑定到的NSController 上调用它。这可能是NSArrayControllerNSTreeController 或只是一个普通的NSObjectController。如果您将控件直接绑定到模型对象而不是通过NSObjectController,那么您应该更改绑定以使用NSObjectController 作为中间对象。主要原因是NSObjectController 将使用NSEditorRegistration 协议告诉控件完成编辑,而普通绑定不会。
  • 嗯,很有趣。这对我来说是新的,在我最初学习 Cocoa 编程的书中根本没有提到。我会调查一下。使用我的方法是否有问题(如我的回答中所述)或者这是否被视为 hack
  • 不幸的是,关于 Cocoa Bindings 的好信息并不多,而且没有人曾经出于某种原因谈论NSEditorRegistration。您的解决方案可能有点有点 hacky,因为您依靠第一响应者的修改来做正确的事情,幸运的是,它可能会这样做。研究commitEditing 方法肯定会更好(当然也更优雅)。
  • 如前所述,我用来学习 Cocoa 编程的书是 Aaron Hillegass 的 Cocoa Programming for Mac OS X - 4ed。使用makeFirstResponder 方法是他“结束编辑”的方式,而不是commitEditing。我想知道为什么。无论如何,我现在先离开它 - 我有一大堆代码要编写,以便在另一个自定义视图中布局复杂的文本对象,首先要担心。
【解决方案2】:

解决方案是在由 OK 按钮调用的操作方法中“结束编辑”。由于窗格是NSWindowController 的子类,NSWindow 很容易访问,但是在您的代码中,您可能必须通过绑定到控制器的控件来获取NSWindow;例如NSWindow *window = [_someControl window]

下面是我的okPressed动作方法的实现。

总之,我相信这是在绑定控件中设置连续更新更好解决方案。

- (IBAction)okPressed:(id)sender
{
    NSWindow *window = [self window];
    BOOL editingEnded = [window makeFirstResponder:window];
    if (!editingEnded)
    {
        logwrn(@"Unable to end editing");
        return;
    }

    if (_delegateRespondsToEditComplete)
    {
        [_delegate detailsEditComplete:&_mydetails];
    }
}

【讨论】:

    【解决方案3】:

    虽然这真的很老了,但我绝对不同意这个问题所基于的假设。

    不断更新绑定绝对不贵。我猜你可能会认为这会不断更新值,理解为“定期基于某个时间间隔”。

    但事实并非如此。这只是意味着它会在您更改绑定值时更新。这意味着,当您在 textView 中键入内容时,它会随着您的编写而更新;这就是你在这种情况下想要的。

    【讨论】:

    • 感谢您的评论;然而,仅此而已;这不是答案。
    猜你喜欢
    • 2013-03-07
    • 1970-01-01
    • 1970-01-01
    • 2021-07-27
    • 2011-02-21
    • 1970-01-01
    • 1970-01-01
    • 2011-11-06
    • 1970-01-01
    相关资源
    最近更新 更多