在Cocoa应用程序中禁用撤消/重做
我已经用标准方式(NSUndoManager)实现了撤销/重做,但我不知道在我的应用程序处于特定状态时如何禁用撤销/重做 用户在我的应用程序中绘制东西,当他们绘制的东西上传时,我禁用UI,当然不希望用户能够撤消/重做在Cocoa应用程序中禁用撤消/重做,cocoa,undo,nsundomanager,Cocoa,Undo,Nsundomanager,我已经用标准方式(NSUndoManager)实现了撤销/重做,但我不知道在我的应用程序处于特定状态时如何禁用撤销/重做 用户在我的应用程序中绘制东西,当他们绘制的东西上传时,我禁用UI,当然不希望用户能够撤消/重做 我使用NSView的撤销管理器,所以我想一种方法可能是让该视图成为第一响应者。还有其他方法吗?我能想到的最佳方法是使视图的-undoManager方法在上载期间返回nil,这将从响应程序链中删除它,并导致该视图的撤消/重做选项被禁用 (我还没有对此进行测试,但我99%确信,每当菜单
我使用NSView的撤销管理器,所以我想一种方法可能是让该视图成为第一响应者。还有其他方法吗?我能想到的最佳方法是使视图的
-undoManager
方法在上载期间返回nil,这将从响应程序链中删除它,并导致该视图的撤消/重做选项被禁用
(我还没有对此进行测试,但我99%确信,每当菜单验证菜单选项时,它将向您的视图询问撤消管理器。)您可以使用完成撤消和重做
- (void) removeAllActions;
或使用删除特定目标的操作
- (void) removeAllActionsWithTarget: (id) target;
如果您只是想在一段时间内禁用任何操作,保持撤消堆栈不变,只需使用NSMenuValidationProtocol的
- (BOOL)validateMenuItem:(NSMenuItem *)menuItem;
如果视图是第一响应程序,则可以根据当前状态实现协议以禁用或启用菜单项
- (BOOL)validateMenuItem:(NSMenuItem *)menuItem {
SEL action = menuItem.action;
if (action == @selector(undo:) ||
action == @selector(redo:)) {
return !uploadingImage;
}
return YES;
}
文档是您的朋友。NSUndoManager的方法名称中有“disable”。由应用程序的控制器决定何时应禁用和重新启用撤消注册。我遇到过类似的情况,我想在应用程序处于特定状态时有条件地禁用某些撤消/重做操作(同时仍允许对其他操作执行撤消/重做) 在视图上实现
-(BOOL)validateNuItem:(NSMenuItem*)项
的方法对我不起作用(我有一个基于10.12的文档应用程序)。根据以下文件:
如果响应程序链中有一个对象实现了该项的操作,则NSMenu会检查该对象是否实现了ValidateNuItem:或validateUserInterfaceItem:方法。如果没有,则菜单项已启用。如果是,则菜单项的启用状态由方法的返回值确定
视图必须添加一个undo方法,该方法也可以做正确的事情
当我探测响应器链时,我发现我的NSWindow是响应撤消:
(虽然它不是文档化接口的一部分)的对象,因此我当前的计划是使用自定义NSWindow子类,并在IME实现ValidateNuItem
,大致如下:
#import "Window.h"
@implementation SBXWindow
- (instancetype)initWithContentRect:(NSRect)contentRect styleMask:(NSWindowStyleMask)style backing:(NSBackingStoreType)bufferingType defer:(BOOL)flag screen:(NSScreen *)screen
{
self = [super initWithContentRect:contentRect styleMask:style backing:bufferingType defer:flag screen:screen];
return self;
}
- (BOOL)validateMenuItem:(NSMenuItem *)item
{
// Call super imeplementation as it appears to update the menu item title (and potentially other stuff)
BOOL result = [super validateMenuItem:item];
if (result == NO) {
return NO;
}
if (item.action == @selector(undo:) || item.action == @selector(redo:)) {
// Add custom logic here
}
return result;
}
@end
但是,存在以下警告:undo:
redo:
方法未实现。可以通过在NSWindow上创建一个类别来消除这些问题,例如:
@interface NSWindow (SBXUndoable)
- (void)undo:(id)sender;
- (void)redo:(id)sender;
@end
不确定这样做是否有任何问题(我没有注意到),但它确实消除了警告。此后,我将该类更改为Swift类,该类没有任何警告需要处理。是的。成功了。必须实现(iAction)撤销:(id)发送方。这是关于撤销事件的设置,而不是禁用撤销/重做菜单。