在块内使用NSUndoManager

时间:2012-10-02 19:52:05

标签: objective-c macos nsundomanager

我试图在块代码中添加一些撤消/重做(从NSOpenPanel导入一些文件),只要代码来自块,主代码就可以工作,但NSUndoManager代码不会保存,也不会出现任何错误。 NSUndoManager代码可以在其他任何地方工作,只要它不在块

示例NSUndoManager代码如下:

// Undo Work
id  undoObject = [NSApp targetForAction:@selector(undoManager) to:nil from:self];
NSUndoManager *undoManager = [undoObject undoManager];
[[undoManager prepareWithInvocationTarget:self] deleteImages];
[undoManager setActionName:@"import images"];

以下显示代码执行和不执行的位置:

/* NSUndoManager code works */ 
NSOpenPanel *openPanel = [NSOpenPanel openPanel];
[openPanel beginSheetModalForWindow:[self.windowController window]
                  completionHandler:^(NSInteger result) {
                      if (result == NSFileHandlingPanelOKButton) {
                          /* NSUndoManager code does not work, 
                             it also does not work inside importImages: */
                          [self importImages:[openPanel URLs]];
                      } else {
                          [openPanel close];
                      }
                  }];
/* NSUndoManager code works */

1 个答案:

答案 0 :(得分:0)

该块在堆栈上,因此当调用撤消操作时,撤销管理器对象可能已经被释放(或者如果不是这样,则设置为nil)。因此,确保撤消管理器将处于活动状态,声明是作为类实例,还是使用__block语法(没有ARC):

__block NSUndoManager* undoManager;
NSOpenPanel *openPanel = [NSOpenPanel openPanel];
[openPanel beginSheetModalForWindow:[self.windowController window]
                  completionHandler:^(NSInteger result) {
                      if (result == NSFileHandlingPanelOKButton) {
                          id  undoObject = [NSApp targetForAction:@selector(undoManager) to:nil from:self];
                          undoManager=[undoObject undoManager];
                          [[undoManager prepareWithInvocationTarget:self] deleteImages];
                          [undoManager setActionName:@"import images"];
                          [self importImages:[openPanel URLs]];
                      } else {
                          [openPanel close];
                      }
                  }];

完成撤消管理器后,您可以将其设置为nil。