Objective-C撤消管理器问题

时间:2011-06-12 16:57:52

标签: objective-c cocoa key-value-observing nsarraycontroller key-value-coding

我正在阅读一本关于Objective-c的书并了解撤消管理器。这个概念看起来很简单,但提供的例子似乎过于复杂。基本上,我有一个连接到NSArrayController的表视图,我添加或删除数组的人,我可以编辑他们的名字和东西。因为该示例使用NSArrayController和绑定,所以添加和删除都是自动的,所有编辑都是自动的。

要使用撤消管理器,根据我的理解,我需要实现自己的方法来添加/删除/编辑。

由于密钥值编码,我实现了这些方法来执行添加和删除以及自动调用:

- (void)removeObjectFromEmployeesAtIndex:(int)index;
- (void)insertObject:(Person *)p inEmployeesAtIndex:(int)index;

然后进行编辑,我必须将该类注册为观察者并观察编辑的变化:

- (void)changeKeyPath:(NSString *)keyPath
             ofObject:(id)obj
              toValue:(id)newValue

以下是我的问题:

  1. 为什么我要这么做?我的理解是,使用NSArrayController和绑定应该能够更轻松,更自动地添加/删除/编辑项目。但是,如果我必须手动实现所有这些方法只是为了添加撤销支持,为什么要使用NSArrayController或绑定呢?

  2. 幕后发生了什么?在Interface Builder中,添加按钮连接到NSArrayController上的add方法。然后如何调用我的insertObject方法?我知道这是通过键值编码但是什么使得NSArrayController的add方法被覆盖只是b / c我的文档实现了这个方法?

  3. 解决方案是不对称的。我使用一个概念来处理撤消添加/删除和另一个概念来处理撤消编辑。难道我也不能只观察阵列的变化吗?我想这会使observeValueForKeyPath方法复杂化,但这会更有意义吗?

1 个答案:

答案 0 :(得分:2)

1)差不多,但并不完全。如果您认为您的应用程序代码分为三个整体区域:模型,视图和控制器(as documented here),那么Cocoa / XCode环境为您提供了一种处理每个基础知识的“无代码”方式:IB对于视图,模型的核心数据和控制器的绑定/对象控制器。

撤消管理主要是模型的关注点,而不是视图或控制器。因此,管理这些东西并不是Bindings或Object控制器的工作。看起来你的问题是你正在使用数组作为你的数据对象,它们太轻了,无法处理这些东西。如果你想要撤销支持,你将需要使用核心数据来处理模型并免费提供这些东西,或者手动滚动你自己的模型对象(可能包含数组)处理这个逻辑。

FWIW,一旦完成此操作,绑定将间接使您的生活更加轻松,因为当撤消命令将您的数据恢复到之前的状态时,视图将自动反映更改。

此外,NSArrayController的名称有点误导 - 它不是'控制阵列'。它实际上用于控制与其他数据对象有很多关系的数据对象。这让我开始......

2)KVC allows you to treat a to-many relationship在对象和其他对象之间作为数组或集合,无论实际关系如何实现。它是通过要求您实现方法fitting a naming convention来实现的,very closely match the primitive methods of arrays and sets。符合KVC的对象将在您调用mutableArrayValueForKey:mutableSetValueForKey:时返回代理数组或设置,这会将这些方法公开为数组。粗略地说,这就是NSArrayController知道要调用什么的方式--- KVC在数组的原始对象和从密钥生成的一些方法之间进行映射。由于您不希望将数组用作数据对象,因此将任何多对多关系视为普通集合通常非常有用。

3)我认为这与你在错误的地方处理撤销有关。实现KVC-compliant methods以获取/设置数据对象中的属性,让它们在设置数据的同时更新undoManger。您需要一种特殊的方法来让undomanager还原更改,因为您不希望将undos记录为可撤消。或者您可以使用Core Data并免费获得所有这些内容......