Objective-C 撤消管理器问题

JPC*_*JPC 5 cocoa objective-c key-value-observing key-value-coding nsarraycontroller

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

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

由于键值编码,我已经实现了这些方法来进行添加和删除并自动调用:

- (void)removeObjectFromEmployeesAtIndex:(int)index;
- (void)insertObject:(Person *)p inEmployeesAtIndex:(int)index;
Run Code Online (Sandbox Code Playgroud)

然后为了编辑,我必须将该类注册为观察者并观察更改以进行编辑:

- (void)changeKeyPath:(NSString *)keyPath
             ofObject:(id)obj
              toValue:(id)newValue
Run Code Online (Sandbox Code Playgroud)

以下是我的问题:

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

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

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

Chr*_*eux 2

1)接近,但不完全是。如果您认为您的应用程序代码分为三个总体区域:模型、视图和控制器(如此处所述),那么 Cocoa/XCode 环境为您提供了一种“无代码”方式来处理每个区域的基础知识:IB视图、模型的核心数据以及控制器的绑定/对象控制器。

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

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

另外,NSArrayController 的名称有点误导——它不是用来“控制数组”的。它实际上用于控制与其他数据对象具有多对多关系的数据对象。这让我想到...

2) KVC 允许您将一个对象与其他对象之间的多对关系视为数组或集合,而不管该关系实际是如何实现的。它通过要求您实现符合命名约定的方法来实现这一点,这些方法与数组和集合的原始方法非常匹配mutableArrayValueForKey:当您调用或时,符合 KVC 的对象将返回代理数组或设置mutableSetValueForKey:,这会将这些方法公开为数组。粗略地说,这就是 NSArrayController 知道要调用什么的方式 --- KVC 在数组的原始对象和从键生成其鬃毛的一些方法之间进行映射。由于您不想使用数组作为数据对象,因此能够将任何一对多关系视为普通集合通常非常有用。

3)我认为这与您在错误的位置处理撤消有关。实现符合 KVC 的方法来获取/设置数据对象中的属性,让它们在设置数据的同时更新 undoManger。您需要一种特殊的方法让撤消管理器恢复更改,因为您不希望撤消被记录为可撤消。或者你可以只使用 Core Data 并免费获得所有这些东西......