如何为Core Data命名Undo菜单条目通过绑定和NSArrayController添加/删除项目?

时间:2014-05-15 20:06:33

标签: objective-c cocoa core-data nsarraycontroller nsundomanager

我有一个NSTableView填充了一个核心数据实体和添加项目/删除项目按钮,所有这些按钮都连接了NSArrayController和接口生成器中的绑定。

撤消/重做菜单项可以撤消或重做添加/删除项目操作。

但菜单条目仅被称为“撤消”。 “重做”。
我怎么称它们为“撤消添加项目”,“撤消删除项目”等等。

(我知道之前曾问过类似的问题,但接受的答案是a single, now rotten linkthe advice to subclass NSManagedObject and override a method that Apples documentation says about: "Important: You must not override this method.“

2 个答案:

答案 0 :(得分:2)

在项目中添加NSArrayController的子类作为文件。在xib中,在阵列控制器的Identity Inspector中,将Class从NSArrayController更改为新的子类。

覆盖- newObject方法。

- (id)newObject
{
    id newObj = [super newObject];

    NSUndoManager *undoManager = [[[NSApp delegate] window] undoManager];
    [undoManager setActionName:@"Add Item"];

    return newObj;
}

也是- remove:sender方法。

- (void)remove:(id)sender
{
    [super remove:sender];

    NSUndoManager *undoManager = [[[NSApp delegate] window] undoManager];
    [undoManager setActionName:@"Remove Item"];
}

答案 1 :(得分:0)

注册NSManagedObjectContextObjectsDidChangeNotification:

[[NSNotificationCenter defaultCenter] addObserver: self
                                         selector: @selector(mocDidChangeNotification:)
                              name:NSManagedObjectContextObjectsDidChangeNotification
                                           object: nil];

并在相应的方法中解析userInfo字典:

- (void)mocDidChangeNotification:(NSNotification *)notification
{
    NSManagedObjectContext* savedContext = [notification object];

    // Ignore change notifications for anything but the mainQueue MOC
    if (savedContext != self.managedObjectContext) {
        return;
    }

    // Ignore updates -- lots of noise from maintaining user-irrelevant data

    // Set actionName for insertion
    for (NSManagedObject* insertedObject in 
           [notification.userInfo valueForKeyPath:NSInsertedObjectsKey])
    {
        NSString* objectClass = NSStringFromClass([insertedObject class]);
        savedContext.undoManager.actionName = savedContext.undoManager.isUndoing ? 
            [NSString stringWithFormat:@"Delete %@", objectClass] : 
            [NSString stringWithFormat:@"Insert %@", objectClass];
    }   

    // Set actionName for deletion
    for (NSManagedObject* deletedObject in 
           [notification.userInfo valueForKeyPath:NSDeletedObjectsKey])
    {
        NSString* objectClass = NSStringFromClass([deletedObject class]);
        savedContext.undoManager.actionName = savedContext.undoManager.isUndoing ? 
            [NSString stringWithFormat:@"Insert %@", objectClass] : 
            [NSString stringWithFormat:@"Delete %@", objectClass];
    }

}

我已经在自己的代码中对此进行了测试 - 这很粗糙。可以花更多的时间使actionName更好。我删除了更新的解析,因为:1)多对多关系中对象的插入和删除会生成其他对象的更新2)我不在乎如何发现此时更改了哪些属性

我的类名也不是用户友好的,所以现在是实现所有实体的描述功能的好时机,并使用它而不是类名。

但这至少适用于项目中的所有对象控制器,并且很容易插入和删除。

[edit] 更新了mikeD的建议,以涵盖具有反名的重做。谢谢!