将资源注入 NSManagedObject 子类实例

Posted

技术标签:

【中文标题】将资源注入 NSManagedObject 子类实例【英文标题】:Injecting resources into NSManagedObject subclass instances 【发布时间】:2011-11-26 13:34:07 【问题描述】:

我正在研究如何将资源注入到 NSManagedObject 子类实例中,但找不到合理的方法。

简单地说,我有一个对象,它代表实体的行为方法所需的服务。此服务需要在运行时可用。

在 Plain-Old-Objective-C-Object 中,我只需将此对象作为构造函数参数传递,或者在构造后通过属性设置它。类似于有多少对象需要和使用委托。

但是,awakeFromInsert 和 awakeFromFetch 显然不带参数,我也找不到任何地方可以挂接到 NSManagedObjectContext 以配置 NSManagedObjects 初始化后。

有人对此有解决方案吗?

作为一个完全人为的例子:

@interface ProductEntity : NSManagedObject

@property (nonatomic, retain) NSNumber *unitPrice;
@property (nonatomic, retain) MyTaxCalculatorService *taxCalculatorService;

- (void)grossPriceForUnits:(NSUInteger)units;

@end

@implementation ProductEntity

@dynamic unitPrice;
@synthesize taxCalculatorService

- (void)grossPriceForUnits:(NSUInteger)units

   return [self.taxCalculatorService grossAmountForUnitPrice:self.unitPrice quantity:units];


@end

忽略这是否是计算总价格的最佳方法(这是一个人为的示例),我如何将 taxCalculatorService 实例放入 ProductEntity?我无法覆盖 init,也找不到可以始终调用 [entity setTaxCalculatorService:service] 的任何地方。

想法?

【问题讨论】:

您是在谈论“服务”类的单个共享实例还是每个对象都有自己的实例? 每个实体都有一个服务实例的引用。有些人可能会分享,有些人可能不会。在我设计的示例中,您可以想象某些产品的税收计算策略与其他产品不同。 【参考方案1】:

awakeFromFetch / awakeFromInsert 将始终被调用。您将不得不从另一个方向接近它 - 托管对象将不得不从其他一些类请求“服务”实例(我认为这将是一个类方法) - 在您的 awakeFrom* 方法中是这样的:

self.serviceProvider = [ServiceProvider getServiceProviderForObject:self];

然后您的ServiceProvider 类将拥有有关托管对象的所有信息并可以返回适当的实例。

【讨论】:

这与我正在使用的解决方法非常相似 - 一个单例助手,它保留 NSManagedObjectContext->NSManagedObject 子类类型名称->键+值对的属性的三级字典以在实例上设置。然后,正如您所说, NSManagedObject 子类 awakeFrom(Insert|Fetch) 要求该单例进行最终初始化。虽然这一切都相当复杂 - 我希望有更简单的东西。【参考方案2】:

看起来,你不能直接调用以下吗?

myProductEntityInstance.taxCalculatorService = [[MyTaxCalculatorService alloc] init];

它被定义为具有保留的属性,因此您的托管对象应该保留对它的引用。请注意,在您对实体所在的上下文调用 save 之前,您对托管对象所做的更改不会持久化

【讨论】:

问题是 在哪里 调用它。任何NSFetchRequest 或遵循实体中定义的任何关系都可以使实体存在。理论上,我可以跟踪应用程序中对executeFetchRequest 的每次调用,代码会遍历每个返回实体的图形以查找任何 ProductEntities 并在它们上设置该属性。太可怕了。 哦...而且,为了好玩,其中一些 executeFetchRequests 将隐藏在像 NSFetchedResultsController 这样的框架代码中,因此在这些情况下甚至无法设置属性.【参考方案3】:

在我看来,到目前为止,最简洁的方法是将 GrossAmountForUnitPrice:quantity: 转换为 TaxCalculatorService 类的 Class 方法。

然后您可以调用[TaxCalculatorService grossAmountForUnitPrice:self.unitPrice quantity:units] 而无需实例化 taxCalculatorService 类的实例。

这假定您的 TaxCalculatorService 未使用影响其返回值的状态(例如特定区域设置的税率或类似的税率)进行实例化。如果是这样,您当然需要在此处使用该信息来实例化您所描述的实例,因此如果需要该附加信息,您可以将其作为类方法的附加参数传入。

【讨论】:

以上是关于将资源注入 NSManagedObject 子类实例的主要内容,如果未能解决你的问题,请参考以下文章

为啥会有一个子类 NSManagedObject?

将方法添加到从 NSManagedObject 子类化的类

NSManagedObject 有没有办法将创建的子类导入 xcdatamodel 文件

NSmanagedobject 的子类的子类

使用 NSManagedObject 子类将 NSPopupButton 绑定到 NSArrayContraller

将 NSManagedObject 转换为子类返回 nil