【问题标题】:Objective-C undo manager questionsObjective-C 撤消管理器问题
【发布时间】:2011-06-12 16:57:52
【问题描述】:

我正在阅读一本关于 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 方法被重写只是因为我的文档实现了这个方法?

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

【问题讨论】:

  • 你在使用 Core Data 吗?
  • 不,我还没听说过
  • 在 Core Data 之前学习这一点可以减轻痛苦;那样会更有意义。我可以提供的一点建议是,您会在 Cocoa/Xcode 中找到使用起来非常方便的东西,但通常您必须解决问题。一个具体的例子是使用 IB 来创建 GUI - 做复杂的事情它可能变得无用(对于动画等),你必须进入幕后(IB 在这方面进行了改进,就像 CoreData 为你的问题所做的那样)。似乎您现在已经看到了其中一种情况。我的观点:如果你觉得你正在以艰难的方式做某事,它可能仍然是最好/正确的方式。祝你好运
  • @Nektarios “如果你觉得你正在以艰难的方式做某事,它可能仍然是最好/正确的方式”是一个很好的观点。除此之外,您需要很好地了解绑定和 kvo/kvc,以便了解核心数据在做什么并处理边缘情况。自己编写这类东西可能是一个很好的方法。

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


【解决方案1】:

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

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

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。当您调用 mutableArrayValueForKey:mutableSetValueForKey: 时,符合 KVC 的对象将返回一个代理数组或设置,这会将这些方法公开为一个数组。粗略地说,这就是 NSArrayController 知道调用什么的方式 --- KVC 在数组的原始对象和它从键生成鬃毛的一些方法之间映射。由于您不想将数组用作数据对象,因此能够将任何一对多关系视为普通集合通常非常有用。

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

【讨论】:

  • 感谢您的回答。我现在才刚刚开始阅读 Core Data!
猜你喜欢
  • 2011-05-11
  • 2011-03-13
  • 1970-01-01
  • 1970-01-01
  • 2015-12-09
  • 1970-01-01
  • 1970-01-01
  • 2013-10-04
相关资源
最近更新 更多