检测对NSManagedObject的特定属性的更改 [英] Detecting changes to a specific attribute of NSManagedObject
问题描述
如何检测对 NSManagedObject
的特定属性的更改?在我的核心数据数据模型中,我有一个产品
实体,表示要销售的产品。 产品
实体有几个属性: price
, sku
weight
,,
,
a
产品
更改,我需要执行冗长的计算。因此,我想知道任何 产品
的价格
strong>即使该更改来自合并保存在另一个主题上的上下文。什么是一个好的办法去做这个?我在我的商店有成千上万的产品
对象;显然不可能发送每个 addObserver
消息。
How can I detect changes to a specific attribute of an NSManagedObject
? In my Core Data data model, I have a Product
entity that represents a product for sale. The Product
entity has several attributes: price
, sku
, weight
, numberInStock
, etc. Whenever the price
attribute of a Product
changes, I need to perform a lengthy calculation. Consequently, I would like to know when the price
attribute of any Product
changes, [edit] even if that change comes from merging a context saved on another thread. What is a good way to go about doing this? I have thousands of Product
objects in my store; obviously it's not feasible to send each one an addObserver
message.
我一直使用 NSManagedObjectContextObjectsDidChangeNotification
来检测更改,但它只会通知我托管对象已更改,而不是该对象的属性已更改。只要有<$>任何更改为产品
,我就可以重做计算,但是当不相关的属性更改时,会导致无用的重新计算。我正在考虑制定一个 Price
实体(只包含价格
属性),并使用一对一关系产品
和价格
。这样,我可以检测对 Price
对象的更改,以启动计算。这看起来对我来说太荒谬了。有更好的方法吗?
I have been using NSManagedObjectContextObjectsDidChangeNotification
to detect changes, but it only notifies me that a managed object has changed, not which attribute of that object has changed. I could redo the calculation whenever there's any change to a Product
, but that results in useless recalculations whenever an irrelevant attribute has changed. I'm considering making a Price
entity (that only contains a price
attribute) and using a to-one relationship between Product
and Price
. This way, I can detect changes to Price
objects in order to kick off the calculation. This seems excessively kludgy to me. Is there a better way?
更新:
@railwayparade指出我可以使用 NSManagedObject
的 changedValues
方法来确定每个更新的对象的哪些属性已更改。我完全错过了这个方法,它将完全解决我的问题,如果更改不是在后台线程并合并到主线程的上下文。 (见下一段。)
@railwayparade pointed out that I could use the changedValues
method of NSManagedObject
to determine which properties have changed for each updated object. I completely missed that method, and it would totally solve my problem if the changes weren't being made on a background thread and merged into the main thread's context. (See next paragraph.)
我完全错过了关于 NSManagedObjectContextObjectsDidChangeNotification
工作方式的一个细微之处。据我所知,当另一个线程上保存的托管对象上下文合并到主线程上的上下文(使用 mergeChangesFromContextDidSaveNotification:
)时,生成的 NSManagedObjectContextObjectsDidChangeNotification
仅包含当前在主线程的受管对象上下文中的对象的更改信息。如果更改的对象不在主线程的上下文中,它不会成为通知的一部分。这是有道理的,但不是我期待的。因此,我想使用一对一关系而不是一个属性来获得更详细的更改信息实际上需要检查后台线程的 NSManagedObjectContextDidSaveNotification
,而不是主线程的 NSManagedObjectContextObjectsDidChangeNotification
。当然,简单地使用 NSManagedObject
的 changedValues
方法作为@railwayparade有帮助地指出会更加聪明。然而,我仍然留下的问题,主线程上合并的更改通知不一定包含在后台线程上所做的所有更改。
I completely missed a subtlety about the way that NSManagedObjectContextObjectsDidChangeNotification
works. As far as I can tell, when a managed object context saved on another thread is merged into a context on the main thread (using a mergeChangesFromContextDidSaveNotification:
), the resulting NSManagedObjectContextObjectsDidChangeNotification
only contains change information about objects that are currently in the main thread's managed object context. If a changed object isn't in the main thread's context, it won't be part of the notification. It makes sense, but wasn't what I was anticipating. Therefore, my thought of using a to-one relationship instead of an attribute in order to get more detailed change information actually requires examination of the background thread's NSManagedObjectContextDidSaveNotification
, not the main thread's NSManagedObjectContextObjectsDidChangeNotification
. Of course, it would be much smarter to simply use the changedValues
method of NSManagedObject
as @railwayparade helpfully pointed out. However, I'm still left with the problem that the change notification from the merge on the main thread won't necessarily contain all of the changes made on the background thread.
推荐答案
这种情况是你需要一个自定义的NSManagedObject子类。您需要子类,因为您要对托管对象添加一个行为,对价格变化做出反应。
This type of circumstance is where you need a custom NSManagedObject subclass. You need the subclass because you are adding a behavior, reacting to a price change, to the managed object.
在这种情况下,您将覆盖 price
属性的访问器。使用数据模型编辑器中的弹出菜单创建自定义子类。然后选择 price
属性,并选择将Obj-C 2.0实现复制到剪贴板。它会给你很多东西,但关键点将是这样:
In this case, you would override the accessor for the price
attribute. Create a custom subclass using the popup menu in the data model editor. Then select the price
attribute and choose 'Copy Obj-C 2.0 Implementation to the Clipboard`. It will give you a lot of stuff but the key bit will look like this:
- (void)setPrice:(NSNumber *)value
{
[self willChangeValueForKey:@"price"];
[self setPrimitivePrice:value];
[self didChangeValueForKey:@"price"];
}
只需添加代码来处理价格变化即可。每当特定产品的价格变化时,代码将运行。
Just add the code to deal with the price change and you are done. Anytime a specific product's price changes, the code will run.
这篇关于检测对NSManagedObject的特定属性的更改的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!