NSUndoManager无法正常工作。 Aaron Hillegass第9章

时间:2011-10-26 20:03:53

标签: objective-c macos cocoa

我一直在为Aaron Hillegass的Mac OS X进行可可编程。我已经陷入了第9章。我添加了必要的2种方法来允许调用撤销和重做函数。但是,当我构建并运行应用程序时,根据本书,应该自动调用这些方法,但它们不是。它们拼写正确,如下所示......

MyDocument.m中的其他2个方法

- (void)insertObject:(Person *)p inEmployeesAtIndex:(int)index
{
    NSLog(@"Adding %@ to %@", p, employees);
        //Add the inverse of this operation to the undo stack
    NSUndoManager *undo = [self undoManager];
    [[undo prepareWithInvocationTarget:self]removeObjectFromEmployeesAtIndex:index];
    if (![undo isUndoing]){
        [undo setActionName:@"Insert Person"];
    }
        //Add teh person to the array
    [employees insertObject:p atIndex:index];
}

- (void)removeObjectFromEmployeesAtIndex:(int)index
{
    Person *p = [employees objectAtIndex:index];
    NSLog(@"Removing %@ to %@", p, employees);
        //Add the inverse of this operation to the undo stack
    NSUndoManager *undo = [self undoManager];
    [[undo prepareWithInvocationTarget:self]insertObject:p inEmployeesAtIndex:index];
    if (![undo isUndoing]){
        [undo setActionName:@"Delete Person"];
    }
    [employees removeObjectAtIndex:index];
}

myDocument.h

#import <Cocoa/Cocoa.h>
@class Person;

@interface MyDocument : NSDocument
{
    NSMutableArray *employees;
}
- (void)setEmployees:(NSMutableArray *)a;
- (void)removeObjectFromEmployeesAtIndex:(int)index;
- (void)insertObject:(Person *)p inEmployeesAtIndex:(int)index;
@end

任何帮助都会很棒,谢谢:)

3 个答案:

答案 0 :(得分:0)

您尚未为employees实施getter。假设您打算使用键值编码直接或通过Bindings修改数组,您需要为此对象实现此对象的getter和setter,使其符合此属性的KVC。

一旦达到KVC合规性的最低要求,KVC将识别该属性并使用其访问器,包括您实现的任何阵列访问器。

如果您查看调试器控制台,您可能会发现KVC已经以“<Some object> is not KVC-compliant for <some property>”例外的形式告诉您。

答案 1 :(得分:0)

或者,如果您没有使用KVC访问此属性,那么您需要确保使用数组访问器来访问它。

如果在保存,恢复或应用修改时,您直接与数组([employees setArray:][employees insertObject:… atIndex…] / [employees removeObjectAtIndex:…])对话,那么您的访问者的副作用就不会发生了,因为你没有使用它们。您在访问器中实现了撤消支持(至少是您展示的两个实现),如果有任何东西通过KVO观察属性,那就是另一个副作用;如果你不使用你的访问者,这两件事都不会发生。

如果您的setEmployees:访问者未与撤销管理器通信(您在问题中省略了该代码,我无法分辨),则不会添加撤消操作。如果您与它交谈,撤销管理器将正常工作,但如果您不这样做,则它不能。

您必须发送自己的insertObject:inEmployeesAtIndex:removeObjectFromEmployeesAtIndex:消息,以便将更改记录在撤消管理器中,如果这些更改是您与撤消管理器通话的唯一位置。如果您想要批量替换(setEmployees:)可撤销,那么您还必须向管理员添加撤消操作。

答案 2 :(得分:0)

我发现了这个问题。我的阵列控制器没有绑定到文件所有者。这样做之后,所有神奇似乎都有效!我真的希望在本书结束时我会开始理解至少其中一些:(谢谢,无论如何