【发布时间】:2020-01-20 18:58:18
【问题描述】:
我有一个核心数据应用程序,其 NSTableView 绑定到 NSArrayController。我使用数组控制器管理添加和删除对象。我正在尝试添加撤消/重做支持,因此当一个人使用菜单项从表视图中删除对象时,他们可以撤消删除。
我的删除方法是:
- (IBAction)removeHost:(id)sender
{
NSInteger row = [bookmarkList selectedRow];
// Get the object so we can get to the attributes of the host
NSArray *a = [bookmarksController arrangedObjects];
NSManagedObject *object = [a objectAtIndex:row];
if (!object) return;
NSManagedObjectContext *managedObjectContext = [self managedObjectContext];
NSUndoManager *undoManager = [managedObjectContext undoManager];
if (managedObjectContext.undoManager == nil)
{
NSLog(@"No undo manager in app controller!");
} else {
NSLog(@"We've got an undo manager in app controller!");
}
[undoManager registerUndoWithTarget:self selector:@selector(addBookmarkObject:) object:object];
[bookmarksController removeObject:object];
[undoManager setActionName:@"Bookmark Delete"];
}
删除对象可以正常工作,但撤消不能。 Command-Z 菜单项永远不会启用。我设置了一个临时菜单项和操作来测试 undoManager,
- (IBAction)stupidUndoRemoveHost:(id)sender
{
NSManagedObjectContext *managedObjectContext = [self managedObjectContext];
NSUndoManager *undoer = [managedObjectContext undoManager];
NSLog(@"canUndo? %hhd", [undoer canUndo]);
NSLog(@"canRedo? %hhd", [undoer canRedo]);
NSLog(@"isUndoRegistrationEnabled? %hhd", [undoer isUndoRegistrationEnabled]);
NSLog(@"undoMenuItemTitle = %@", [undoer undoMenuItemTitle]);
NSLog(@"redoMenuItemTitle = %@", [undoer redoMenuItemTitle]);
[undoer undo];
}
使用这个 IBAction 我可以撤消(嗯,有点,它添加了两次对象,很明显这里还有更多错误),但我只能做一次。如果我删除另一个对象 canUndo 返回 0,而愚蠢的UndoRemoveHost 什么也不做。
我知道我不明白这里的某些内容。我在这里阅读的帖子数不胜数,还有几篇博客文章和Apple documentation。我以前也这样做过,但就像十年前一样,所以我的技能有点生疏。非常感谢任何正确方向的帮助或指示。
更新:这里是 addBookmarkObject 方法:
- (void)addBookmarkObject: (NSManagedObject *)object
{
[bookmarksController addObject:object];
}
这是来自 AppDelegate 的windowWillReturnUndoManager:
- (NSUndoManager *)windowWillReturnUndoManager:(NSWindow *)window {
// Returns the NSUndoManager for the application. In this case, the manager returned is that of the managed object context for the application.
NSUndoManager *undoManager = [[NSUndoManager alloc] init];
self.persistentContainer.viewContext.undoManager = undoManager;
if (self.persistentContainer.viewContext.undoManager == nil)
{
NSLog(@"No undo manager!");
} else {
NSLog(@"We've got an undo manager!");
}
return self.persistentContainer.viewContext.undoManager;
}
【问题讨论】:
-
显示 addBookmarkObject 的代码。我没有看到 removeHost 中的代码有任何问题。
-
谢谢,我已经用更多代码更新了这个问题。
-
托管对象上下文的撤消管理器应该处理撤消,您不必自己实现它。为什么要替换
windowWillReturnUndoManager:中的撤消管理器?这是一个基于文档的应用程序吗? -
它不是基于文档的,我在之前的故障排除步骤中添加了它。我将删除自定义撤消管理器并重试。
-
@Willeke 如果我没有在 App Delegate 的
windowWillReturnUndoManager中初始化 undoManager,则没有撤消管理器。登录我的 App Controller 的stupidUndoRemoveHost显示没有撤消管理器,在委托中也是如此。
标签: objective-c cocoa core-data nsundomanager