Re: Core Data design question: receiving KVO notifications of partially mutated objects
On 11/2/09 12:58 PM, Ben Trumbull said: >This doesn't really have anything to do with Core Data. However, for >NSManagedObject, Core Data already provides the change coalescing and >NSNotifications for you. You can respond within >NSManagedObjectContextObjectsDidChangeNotification instead. So I read the various archive posts about that notification and played with it a little. I can see it being handy, especially for added and removed objects. The big shortcoming, in my situation anyway, is that it does not seem to provide me with the keys that changed (in the NSUpdatedObjectsKey case). Unless I'm missing something? Thanks, -- Sean McBride, B. Eng s...@rogue-research.com Rogue Researchwww.rogue-research.com Mac Software Developer Montréal, Québec, Canada ___ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) Please do not post admin requests or moderator comments to the list. Contact the moderators at cocoa-dev-admins(at)lists.apple.com Help/Unsubscribe/Update your Subscription: http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com
Re: Core Data design question: receiving KVO notifications of partially mutated objects
>> If your issue is that drawing or recalculation is occurring too >> frequently after KVO changes, you can consider coalescing and deferring >> the observers' actions instead of performing them synchronously. This >> can be valuable even for less complex KVO issues. >> >> You could also refactor the 3 properties into 1 object. > > Alas, that would require 1) persistent store migration (painful on 10.5) > and 2) I find it very handy to be able to bind 'colour' to a colourwell > and 'width' and 'height' to text fields. Perhaps I have bent my model > too much in favour of my UI also. :) But anyway, this 'Rectangle' > object was just an example. My real app is a bit harder to explain. > >> Or use an >> NSNotification instead of KVO to adjust the granularity of notifications >> to better suit your drawing code. >> >> This doesn't really have anything to do with Core Data. However, for >> NSManagedObject, Core Data already provides the change coalescing and >> NSNotifications for you. You can respond within >> NSManagedObjectContextObjectsDidChangeNotification instead. > > Perhaps NSManagedObjectContextObjectsDidChangeNotification is the thing > I have overlooked! I currently use it almost nowhere but have tonnes > and tonnes of KVO observing going on. > > I'll have to RTFM on NSManagedObjectC > ontextObjectsDidChangeNotification. Questions that pop to mind though: > is it safe for me to fetch? to create/delete/mutate ManagedObjects? I'd recommend performing a selector after delay 0. You can inspect the objects and decide what you want to do with them. The notification is posted from within the change tracking code, so making changes could possibly result in them getting caught in between 1 user event and the next. - Ben ___ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) Please do not post admin requests or moderator comments to the list. Contact the moderators at cocoa-dev-admins(at)lists.apple.com Help/Unsubscribe/Update your Subscription: http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com
Re: Core Data design question: receiving KVO notifications of partially mutated objects
On 11/2/09 12:58 PM, Ben Trumbull said: >> What is considered best practice when it comes to mutating many >> properties of a managed object, specifically with regard to KVO >> observers getting notified before all mutations are finished? > >This is a problem intrinsic to the design of KVO. KVO is all about fine >grained per property notifications. It's very well suited to that. >However, it's common for complex objects to be in an intermediate state >during a KVO notification. > >There's no better notion of cross-property coherence than refactoring >into a different property object that encapsulates everything. > >> Let's say I have an Rectangle object. It has properties: colour, width, >> height. Imagine some controller observing all these properties, perhaps >> to trigger a redraw. >> >> If I do: >> >> [rect setColour:...]; >> [rect setWidth:...]; >> [rect setHeight:...]; > >In this example, the best KVO can do is work with a "colored rectangle" >object that in turn is the 1 property you work with here. So, this >would be an example of a granularity of notification that works better >with NSNotificationCenter > >> This is short and readable. But observers will be notified after each >> setter. > >yup > >> This could be a problem if intermediate states are not self- >> consistent and could also lead to unnecessary redrawing. > >And many other performance issues if observers recalculate things too >aggressively. > >> In the general case, I might not even know who is observing. > >Well, that's the point of the notification pattern. > >> >> I guess it's safer to create a setColour:width:height: method in my >> NSManagedObject subclass that does: >> >> [self willAccessValueForKey:@"colour"]; >> [self willAccessValueForKey:@"width"]; >> >> [self setPrimitiveColour:...]; >> [self setPrimitiveWidth:...]; >> >> [self didAccessValueForKey:@"width"]; >> [self didAccessValueForKey:@"colour"]; >> >> Is this what I should be doing? > >Generally, no. (setting aside, the calls should be to >willChangeValueForKey:, btw) Ben, Thanks for all the above comments, they have each connected a few dots in my mind. >If your issue is that drawing or recalculation is occurring too >frequently after KVO changes, you can consider coalescing and deferring >the observers' actions instead of performing them synchronously. This >can be valuable even for less complex KVO issues. > >You could also refactor the 3 properties into 1 object. Alas, that would require 1) persistent store migration (painful on 10.5) and 2) I find it very handy to be able to bind 'colour' to a colourwell and 'width' and 'height' to text fields. Perhaps I have bent my model too much in favour of my UI also. :) But anyway, this 'Rectangle' object was just an example. My real app is a bit harder to explain. >Or use an >NSNotification instead of KVO to adjust the granularity of notifications >to better suit your drawing code. > >This doesn't really have anything to do with Core Data. However, for >NSManagedObject, Core Data already provides the change coalescing and >NSNotifications for you. You can respond within >NSManagedObjectContextObjectsDidChangeNotification instead. Perhaps NSManagedObjectContextObjectsDidChangeNotification is the thing I have overlooked! I currently use it almost nowhere but have tonnes and tonnes of KVO observing going on. I'll have to RTFM on NSManagedObjectC ontextObjectsDidChangeNotification. Questions that pop to mind though: is it safe for me to fetch? to create/delete/mutate ManagedObjects? Ultimately, my recent problem with 'dangling reference to an invalid object' made me realise I probably have some design problems, which I can't quite put my finger on. I'm pretty sure I'm misusing/abusing KVO however. Thanks, -- Sean McBride, B. Eng s...@rogue-research.com Rogue Researchwww.rogue-research.com Mac Software Developer Montréal, Québec, Canada ___ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) Please do not post admin requests or moderator comments to the list. Contact the moderators at cocoa-dev-admins(at)lists.apple.com Help/Unsubscribe/Update your Subscription: http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com
Re: Core Data design question: receiving KVO notifications of partially mutated objects
Graham, Thanks for the detailed reply! >I'd say you're going down the wrong path there. Agreed, hence my post. :) >Set each property individually. Yes, it will trigger a notification >for each one - doesn't or shouldn't matter, and unless you can show it >causes a performance problem, shouldn't be a cause for worry on that >score. It won't cause multiple redrawing, because even if each one >posted a -setNeedsDisplayInRect:, the actual drawing will not get >processed until the next update cycle and invalidating the same area >three times still only results in one redraw, by which time all the >properties will be set. Drawing performance is not an issue here >(unless you are bypassing the update mechanism and forcing the drawing >on a notification, but that's a different wrong, so you're not doing >that, are you?). My 'Rectangle' object with colour, width, and height attributes was an example of course. I should probably have clarified that or just not have used drawing as an example. You are right about the whole redraw mechanism of course, and my drawing is in fact fine, and I'm not doing anything mischievous there. >The question of whether the separate notifications lead to an invalid >intermediate state is a more reasonable problem to consider, but it >normally shouldn't matter either. Normally KVO will be used to update >your UI and/or maintain undo. You mention Core Data so that will >handle undo for you but even if you were doing that yourself it >shouldn't matter. Undo will record each property change and group >them, so you end up with one undo that undoes all three property >changes. Any UI that represents each property will also update all at >once (or appear to) because the drawing update cycle won't actually >show changes until the update runs and flushes the changes to the >backing store. In general, I've found things do indeed work that way, and they work well. >As a general rule you can and should treat each property in isolation. >Even if some command sets several at once, you should find that it all >works correctly unless you've gone out of your way to depend on some >property state always being paired with some other property state, in >which case you should probably make that state pair a separate >property. I think as a general rule the approach you're proposing is >unnecessary and untidy. I'm starting to think perhaps the root of my problem is that I am using KVO in my controller layer to do things that should be done in my model layer. Sometimes the creation of one ManagedObject, say type 'Foo', requires that: - several other ManagedObjects be created and related. - several existing ManagedObjects be found and related. Where is the right place to do such a thing? Currently, I often do it by KVO observing, in my NSDocument, the creation of new Foos. When I detect new ones, I'll perform some fetches, create new objects, relate them appropriately, etc. (In the past, I tried doing such things inside Foo's awakeFromInsert but I discovered that performing a fetch from that function leads to various problems.) Thanks, -- Sean McBride, B. Eng s...@rogue-research.com Rogue Researchwww.rogue-research.com Mac Software Developer Montréal, Québec, Canada ___ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) Please do not post admin requests or moderator comments to the list. Contact the moderators at cocoa-dev-admins(at)lists.apple.com Help/Unsubscribe/Update your Subscription: http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com
re: Core Data design question: receiving KVO notifications of partially mutated objects
> What is considered best practice when it comes to mutating many > properties of a managed object, specifically with regard to KVO > observers getting notified before all mutations are finished? This is a problem intrinsic to the design of KVO. KVO is all about fine grained per property notifications. It's very well suited to that. However, it's common for complex objects to be in an intermediate state during a KVO notification. There's no better notion of cross-property coherence than refactoring into a different property object that encapsulates everything. > Let's say I have an Rectangle object. It has properties: colour, width, > height. Imagine some controller observing all these properties, perhaps > to trigger a redraw. > > If I do: > > [rect setColour:...]; > [rect setWidth:...]; > [rect setHeight:...]; In this example, the best KVO can do is work with a "colored rectangle" object that in turn is the 1 property you work with here. So, this would be an example of a granularity of notification that works better with NSNotificationCenter > This is short and readable. But observers will be notified after each > setter. yup > This could be a problem if intermediate states are not self- > consistent and could also lead to unnecessary redrawing. And many other performance issues if observers recalculate things too aggressively. > In the general case, I might not even know who is observing. Well, that's the point of the notification pattern. > > I guess it's safer to create a setColour:width:height: method in my > NSManagedObject subclass that does: > > [self willAccessValueForKey:@"colour"]; > [self willAccessValueForKey:@"width"]; > > [self setPrimitiveColour:...]; > [self setPrimitiveWidth:...]; > > [self didAccessValueForKey:@"width"]; > [self didAccessValueForKey:@"colour"]; > > Is this what I should be doing? Generally, no. (setting aside, the calls should be to willChangeValueForKey:, btw) If your issue is that drawing or recalculation is occurring too frequently after KVO changes, you can consider coalescing and deferring the observers' actions instead of performing them synchronously. This can be valuable even for less complex KVO issues. You could also refactor the 3 properties into 1 object. Or use an NSNotification instead of KVO to adjust the granularity of notifications to better suit your drawing code. This doesn't really have anything to do with Core Data. However, for NSManagedObject, Core Data already provides the change coalescing and NSNotifications for you. You can respond within NSManagedObjectContextObjectsDidChangeNotification instead. - Ben ___ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) Please do not post admin requests or moderator comments to the list. Contact the moderators at cocoa-dev-admins(at)lists.apple.com Help/Unsubscribe/Update your Subscription: http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com
Re: Core Data design question: receiving KVO notifications of partially mutated objects
Hi Sean, I'd say you're going down the wrong path there. Set each property individually. Yes, it will trigger a notification for each one - doesn't or shouldn't matter, and unless you can show it causes a performance problem, shouldn't be a cause for worry on that score. It won't cause multiple redrawing, because even if each one posted a -setNeedsDisplayInRect:, the actual drawing will not get processed until the next update cycle and invalidating the same area three times still only results in one redraw, by which time all the properties will be set. Drawing performance is not an issue here (unless you are bypassing the update mechanism and forcing the drawing on a notification, but that's a different wrong, so you're not doing that, are you?). The question of whether the separate notifications lead to an invalid intermediate state is a more reasonable problem to consider, but it normally shouldn't matter either. Normally KVO will be used to update your UI and/or maintain undo. You mention Core Data so that will handle undo for you but even if you were doing that yourself it shouldn't matter. Undo will record each property change and group them, so you end up with one undo that undoes all three property changes. Any UI that represents each property will also update all at once (or appear to) because the drawing update cycle won't actually show changes until the update runs and flushes the changes to the backing store. As a general rule you can and should treat each property in isolation. Even if some command sets several at once, you should find that it all works correctly unless you've gone out of your way to depend on some property state always being paired with some other property state, in which case you should probably make that state pair a separate property. I think as a general rule the approach you're proposing is unnecessary and untidy. --Graham On 31/10/2009, at 9:01 AM, Sean McBride wrote: Let's say I have an Rectangle object. It has properties: colour, width, height. Imagine some controller observing all these properties, perhaps to trigger a redraw. If I do: [rect setColour:...]; [rect setWidth:...]; [rect setHeight:...]; This is short and readable. But observers will be notified after each setter. This could be a problem if intermediate states are not self- consistent and could also lead to unnecessary redrawing. In the general case, I might not even know who is observing. I guess it's safer to create a setColour:width:height: method in my NSManagedObject subclass that does: [self willAccessValueForKey:@"colour"]; [self willAccessValueForKey:@"width"]; [self setPrimitiveColour:...]; [self setPrimitiveWidth:...]; [self didAccessValueForKey:@"width"]; [self didAccessValueForKey:@"colour"]; Is this what I should be doing? I can see it getting ugly with more than 3 or so properties... ___ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) Please do not post admin requests or moderator comments to the list. Contact the moderators at cocoa-dev-admins(at)lists.apple.com Help/Unsubscribe/Update your Subscription: http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com
Re: Core Data design question: receiving KVO notifications of partially mutated objects
On 31/10/2009, at 9:01 AM, Sean McBride wrote: Hi all, What is considered best practice when it comes to mutating many properties of a managed object, specifically with regard to KVO observers getting notified before all mutations are finished? In situations like these I personally tend to avoid KVO. It's too noisy and in some cases incurs too much of a performance overhead. But, I have a solution which I describe below. Let's say I have an Rectangle object. It has properties: colour, width, height. Imagine some controller observing all these properties, perhaps to trigger a redraw. If I do: [rect setColour:...]; [rect setWidth:...]; [rect setHeight:...]; This is short and readable. But observers will be notified after each setter. This could be a problem if intermediate states are not self- consistent and could also lead to unnecessary redrawing. In the general case, I might not even know who is observing. I guess it's safer to create a setColour:width:height: method in my NSManagedObject subclass that does: [self willAccessValueForKey:@"colour"]; [self willAccessValueForKey:@"width"]; [self setPrimitiveColour:...]; [self setPrimitiveWidth:...]; [self didAccessValueForKey:@"width"]; [self didAccessValueForKey:@"colour"]; Is this what I should be doing? I can see it getting ugly with more than 3 or so properties... Perhaps make a property that represents the state of the value these dependent properties contribute to? For example, is it possible to have a "requires redraw" property of the Rectangle? You could simply change the value of that property (in the overridden setColor:, setWidth:, setLength: methods *sigh*) to indicate the Rectangle object requires a redraw? Then, when a third party wants the value of the dependent property, you can recalculate it. In the given example, the rectangle will only re-draw when it's needed. Just a few ideas, not sure if they're of any help. They're not coming from a Core Data perspective either, just a general one - but I wouldn't expect it to be much different? Kiel ___ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) Please do not post admin requests or moderator comments to the list. Contact the moderators at cocoa-dev-admins(at)lists.apple.com Help/Unsubscribe/Update your Subscription: http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com
Core Data design question: receiving KVO notifications of partially mutated objects
Hi all, What is considered best practice when it comes to mutating many properties of a managed object, specifically with regard to KVO observers getting notified before all mutations are finished? Let's say I have an Rectangle object. It has properties: colour, width, height. Imagine some controller observing all these properties, perhaps to trigger a redraw. If I do: [rect setColour:...]; [rect setWidth:...]; [rect setHeight:...]; This is short and readable. But observers will be notified after each setter. This could be a problem if intermediate states are not self- consistent and could also lead to unnecessary redrawing. In the general case, I might not even know who is observing. I guess it's safer to create a setColour:width:height: method in my NSManagedObject subclass that does: [self willAccessValueForKey:@"colour"]; [self willAccessValueForKey:@"width"]; [self setPrimitiveColour:...]; [self setPrimitiveWidth:...]; [self didAccessValueForKey:@"width"]; [self didAccessValueForKey:@"colour"]; Is this what I should be doing? I can see it getting ugly with more than 3 or so properties... Thanks, -- Sean McBride, B. Eng s...@rogue-research.com Rogue Researchwww.rogue-research.com Mac Software Developer Montréal, Québec, Canada ___ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) Please do not post admin requests or moderator comments to the list. Contact the moderators at cocoa-dev-admins(at)lists.apple.com Help/Unsubscribe/Update your Subscription: http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com