1

我试图向块代码添加一些撤消/重做(从 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 */
4

1 回答 1

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。

于 2012-10-20T23:36:17.580 回答