objective-c - 使用适当的撤消管理创建持续更新的自定义控件

标签 objective-c cocoa cocoa-bindings nsundomanager

我正在组合一个自定义 NSView,它通过绑定(bind)处理两个值。正如 Tom Dalling 在问题 Can you manually implement Cocoa bindings? 中概述的那样,我正在根据更新传播这些值.这一切都很好。

为了使控件不断更新,我更新并传播了 -mouseDragged 方法中的值。同样,这工作正常,但它将中间步骤注册到 NSUndoManager,这是我不想要的。因此,我尝试在 -mouseDown 中发出 disableUndoRegistration,然后在 mouseUp 中发出 enableUndoRegistration。我自然会再次更新和传播结果。

根本没有注册撤消,我意识到这是因为如果值不变,我的 set 函数不会注册撤消:

- (void)setX:(double)newX {
    if (newX != x) {
        [[undoManager prepareWithInvocationTarget:self] setX:x];
        [self willChangeValueForKey:@"x"];
        x = newX;
        [self didChangeValueForKey:@"x"];
    }
}

因为 -mouseDragged 已经传播了该值,所以当它在 -mouseUp 中再次发送时它没有改变,所以从未记录撤消。我当然希望它撤消到初始 -mouseDown 之前的位置,所以假设我通过将该值存储在控件中然后在 -mouseUp 中再次发送该值来做到这一点,在我发送新值之前。当然,这仍然存在问题,我可以看到它一闪而过又回到了它的旧值。

我可以在 -setX: 方法中解决这个问题,方法是检查撤消管理器是否启用并跟踪旧值。但是,我应该能够从控件内完成此操作,因为存在具有这种确切行为的控件(例如设置为连续的 NSSlider)。

谢谢!

最佳答案

你不能只使用 beginUndoGroupingendUndoGrouping 吗?


附言如果您对 Cocoa 类的内部工作方式感到好奇,检查 GNUstep 实现有时会有所帮助(NSUndoManager 在 GNUstep Base 中,AppKit 类如 NSSliderCell 在 GNUstep GUI 中):

http://wwwmain.gnustep.org/resources/downloads.php?site=http%3A%2F%2Fftpmain.gnustep.org%2Fpub%2Fgnustep%2F#core

关于objective-c - 使用适当的撤消管理创建持续更新的自定义控件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5913421/

相关文章:

objective-c - 未在 setStringValue 上调用 ControlTextDidChange

xcode - NSTextField 的 "Value With Pattern"绑定(bind)中的条件显示模式

objective-c - 你可以手动实现 Cocoa 绑定(bind)吗?

ios - 使用 MPMoviePlayerController 播放录制的视频时 iOS 7 中的 _itemFailedToPlayToEnd 问题

iOS 6 - 无法访问照片?

ios - NSPredicate 不会工作?

objective-c - 将值绑定(bind)到数组的第 n 个对象

Objective-C 风格

xcode - 单击取消选择 NSCollectionViewItem

cocoa - -[NSResponder showContextHelp :] example