17

我使用 mogenerator 已经有一段时间了,虽然有一个合理的入门指南和关于命令行选项的Stack Exchange 文章,但我还没有找到它提供的所有功能的好的指南。 简而言之:除了 Core Data 为您提供的类之外,mogenerator 实际生成了什么?

(坦率地说,我一直在头文件/实现中发现一些我没有意识到的惊喜,我决定逐步浏览 mogenerator 模板和代码,并记录我在 Stack Exchange Q&A 中发现的内容。我很乐意但是,请参阅其他答案和编辑。)

4

1 回答 1

38

除了两个类系统的核心功能之外,mogenerator 还可以通过在您的机器头文件和实现文件中自动实现一些有关核心数据的最佳实践来帮助您。

属性访问器

访问实体属性的方法是 mogenerator 生成的核心。但是除了开箱即用的 Xcode 类生成器提供给您的访问器之外,还有一些不错的功能在访问器中实现。

标量访问器

Xcode 的内置生成器为您提供“对原始数据类型使用标量属性”的选项。此选项使您可以选择让 Xcode 创建属性,其中NSTimeIntervals 代替NSDates 用于日期类型,BOOLs 代替NSNumbers 用于布尔类型,和int16_t(或类似的)而不是NSNumbers。

我觉得这很令人恼火,因为大多数时候我更喜欢原始类型,但不是 for NSDates 比 a 有用得多NSTimeInterval。所以 Core Data 给了我对象的选择,在这种情况下,我会不断地拆箱并犯一些愚蠢的错误,比如if(myBooleanAttribute)(这总是YES因为myBooleanAttribute是 a NSNumber,而不是 a BOOL)。或者我可以有标量,但在这种情况下,我得到NSTimeIntervals,我总是必须转换为NSDates。或者我可以手动编辑所有生成的文件,给我想要的NSDates 和BOOLs 组合。

另一方面,mogenerator 为您提供了两种选择。例如,您将同时获得一个myBooleanAttribute为您提供NSNumber(以便于在 中存储NSArray)的myBooleanAttributeValuegetter 和一个为您提供实际BOOL. 与整数和浮点数相同。(Mogenerator 不生成NSTimeInterval访问器:仅NSDates。)

类型化的可转换属性

如果您有一个可转换的属性,您可以在属性中设置一个特定的 UserInfo 键 (attributeValueClassName),该键将指定您的属性将返回/接受的类。(它会正确地转发声明类等。)我发现这个记录的唯一地方是Verious

相反,Xcode 代码生成器只会将这些可转换的属性键入为 id 类型。

验证声明

虽然 mogenerator 不会自动生成任何验证方法,但它确实包含正确的签名作为机器 h 文件中的注释。这似乎很大程度上是出于历史原因,但这确实意味着如果您决定在人工文件实现中实现签名,则很容易复制和粘贴签名。(我实际上不会取消注释该声明,因为您不应该直接调用验证。)

原始访问器

Core Data 已经为您提供了这些原始值的访问器,但由于某种原因,它们并未包含在其 Xcode 生成的标头中。让 mogenerator 将它们包含在其头文件中可以更容易地访问原始值。

获取的属性

mogenerator 将为获取的属性生成访问器。据我所知,没有办法让 Xcode 生成器执行此操作。

辅助方法

自动生成 NSFetchedResultsController

如果您的实体中存在多对多关系,并且您将 --template-var frc=true 传递给 mogenerator,则 mogenerator 将自动生成一个方法来为与父对象关联的子对象创建获取请求。它甚至会自动生成一个唯一的缓存名称,并隔离#if TARGET_OS_IPHONE预处理器宏中的所有内容。

即使这不符合您的特定需求,它也是如何扩展模板的一个很好的例子。

+fetchMyFetchRequest:moc_

如果您喜欢在模型中定义获取请求,这比硬编码字符串要好得多。

-MyEntitySet

Mogenerator 使用 KVC 的魔力为NSMutableSet您提供关系代理。

+实体名称

需要为某个NSFetchRequest或其他 Core Data 方法提供实体名称?使用这种简单的方法可以很容易地避免硬编码字符串,该方法将实体的名称作为NSString.

+insertInManagedObjectContext: 和 entityInManagedObjectContext:

避免硬编码实体名称的另一种方法是使用这些辅助方法。

类型化的对象 ID

您的每个标头和实现还包括一个MyEntityID类。它们是空的接口和实现,只是类的子NSManagedObjectID类。此外,每个模型类都有一个名为 objectID 的辅助方法,它覆盖NSManagedObject. 辅助方法只是将超类的返回值转换为MyEntityID类型。

最终结果:如果您不小心交换了来自不同实体的对象 ID,编译器可以捕捉到您的错误。

各种各样的

子类化自定义超类

命令行选项之一是--base-class:允许您指定所有生成的类都将从中继承的基类。这非常有用,您可以有一个基类来定义便捷方法(给定 Core Data,您可能应该这样做),或者您可以使用现成的 Core Data 工具包,如 SSDDataKit(或两者兼有)。

包括

一件简单的小事,但如果您指定 --includem 参数,mogenerator 将生成一个包含所有模型头文件的头文件。如果您想将所有标题包含在 PCH 中,或者包含其他一些标准标题,则很方便。

所有属性、关系、获取的属性的 const 定义

结构的外部声明包含在标头中,该标头NSString为您的实体中定义的每个属性和关系定义。这允许您定义谓词和其他参数,而无需将实体名称烘焙到字符串中。例如,

req.predicate = [NSPredicate predicateWithFormat:
@"(%K == YES) AND (%K <= %@)",MyObject.favorite, MyObject.availableDate, [NSDate date]];

(这种用于“命名空间”常量的结构在他的博客上描述为 My Mike Ash

用户信息键/值的 const 定义

类似地,结构的外部声明在标头中定义,其中包括作为结构成员的键和作为值的值。IE

NSLog(@"User info for key my key is %@",MyObjectInfo.mykey) //will log "myvalue" 

备用模板

关于 mogenerator 的一个有趣的事情是,在构建 mogenerator 时,它的作者(Wolf Rentzsch)基本上为 Xcode 生成的 xcdatamodel 文件构建了一个通用解析器和模板引擎。所以你不需要使用 mogenerator 模板。您可以为自己提供一个简单的命令行参数。GitHub 站点上有很多用户贡献的模板

事实上,你甚至不必使用 Core Data。许多贡献的模板允许您基于数据模型生成一系列普通的 NSObject 模型类。(所谓的 PONSO:“普通的旧 nsobjects”)。想在 Xcode 中使用数据建模器,但想使用其他一些持久性机制?mogenerator 可以帮助您。

您甚至根本不需要生成对象:另一个有趣的提交模板 只是提供了两个不同模型版本的差异。

于 2014-03-21T17:56:19.097 回答