在 NSDocument 和 UIDocument 之间共享代码
Posted
技术标签:
【中文标题】在 NSDocument 和 UIDocument 之间共享代码【英文标题】:Sharing code between NSDocument and UIDocument 【发布时间】:2012-03-26 20:26:00 【问题描述】:我创建了一个使用 Core Data 的基于文档的应用程序。我首先创建了 mac 版本,现在它可以正常工作了,我正在继续创建它的 ios 版本。
关于核心数据位,我只是不知道如何在 iOS/mac 版本之间最大限度地重用代码,因为它们不使用相同的类。
我的文档类处理保存等是NSPersistentDocument
的子类。我的意图是一个设计良好的模型类应该在这两种环境中工作,特别是因为我没有对核心数据做太多花哨的事情。
现在,由于 NSPersistentDocument
在 iOS 中不可用,我碰壁了。我试图通过使用#if TARGET_OS_MAC and TARGET_OS_IPHONE
来解决这个问题,并以这种方式使其成为iOS 版本中UIManagedDocument
的子类。这显然会很方便,但我似乎无法让它像那样工作。而且它看起来真的很乱,因为还有很多其他的东西也需要条件化。
我也尝试在 NSDocument
/UIDocument
之上构建类,自己实现核心数据挂钩,但它看起来也很混乱,让我觉得这不是正确的方法。
问题:
对我来说,在 iOS/mac 版本之间重用相同的文档类似乎是个好主意,但也许我太天真了。
最好的方法是什么?
我是否应该忘记代码共享并为 iOS 版本创建一个单独的文档类来模拟 mac 版本中存在的所有方法?
【问题讨论】:
我无法谈论这个特定场景,但考虑一般情况可能会有所帮助:您有两个必须继承自不同超类的类,但您有想要在它们之间共享的代码.对此(在 ObjC 中)的通常答案是组合:将共享代码放入不同的类中,并从两者中引用该类的实例。 这似乎是个好主意。请张贴是一个答案,我会选择它。一个后续问题,似乎我在我的复合对象中编写了 20-30 个方法,这些方法只将它们转发到专用接收器上完全相同的方法。有没有更好的办法? 【参考方案1】:您要分享的代码与模型相关,我说得对吗?我建议将该代码重构为一个单独的对象,NSDocument
和 UIDocument
都包含该对象(如上面 rickster 建议的那样)。
我使用带有自己的NSManagedObject
子类的DocumentRoot
Core Data 实体,但是如果您不想使用Core Data 管理任何属性,则可以只子类NSObject
。
这听起来可能很奇怪,但NSDocument
和UIDocument
实际上是控制器类。 (具体来说,它们是模型控制器的一部分。)它们的工作是加载模型、设置窗口和保存模型。如果您需要为更高级别的模型对象访问提供接口,则可以在文档根或模型助手类中。
同样NSPersistentDocument
的工作是配置托管对象上下文和持久存储以及处理加载和保存。它不一定需要提供完整的接口来访问模型。
【讨论】:
【参考方案2】:(从我的评论中引用。)
一般来说,你有两个类必须从不同的超类继承但又想共享大量代码的情况是组合。将共享代码放在单独的类中;您的NSDocument
和UIDocument
子类可以各自保留该类的一个实例,并在需要调用该共享代码时向其发送消息。 (尽管正如@noa 提到的,您可能需要考虑所有代码是否都属于您的文档类。)
当然,你最终可能会编写一堆方法,如下所示:
- (id)doSomething
return [sharedController doSomething]
这可能会很痛苦...所以您可能想研究一下 Objective-C 的 message forwarding 系统。
【讨论】:
未来读者请注意:我选择了这个作为问题的答案,但是在我的特殊情况下我不得不放弃它,因为很明显需要编写很多转发方法并且保持最新。相反,我为 iOS 和 mac 实现保留了单独的类,因为它看起来更实用。以上是关于在 NSDocument 和 UIDocument 之间共享代码的主要内容,如果未能解决你的问题,请参考以下文章
在禁用 iCloud 驱动器的情况下运行 CloudKit 应用程序