我正在读一本关于
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
这是我的问题:
>为什么我要这么做?我的理解是,使用NSArrayController和绑定应该能够更轻松,更自动地添加/删除/编辑项目.但是如果我必须手动实现所有这些方法只是为了添加撤销支持,为什么要使用NSArrayController或绑定呢?
>幕后发生了什么?在Interface Builder中,添加按钮连接到NSArrayController上的add方法.然后如何调用我的insertObject方法?我知道这是通过键值编码但是什么使得NSArrayController的add方法被覆盖只是b / c我的文档实现了这个方法?
>解决方案是不对称的.我使用一个概念来处理撤消添加/删除和另一个概念来处理撤消编辑.难道我也不能只观察阵列的变化吗?我想它会使observeValueForKeyPath方法复杂化,但这会更有意义吗?
最佳答案 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并免费获得所有这些东西……