Re: KVO and lazy loading
Re: KVO and lazy loading
- Subject: Re: KVO and lazy loading
- From: Ashley Clark <email@hidden>
- Date: Thu, 23 Oct 2008 01:12:42 -0500
On Oct 23, 2008, at 12:42 AM, Ron Lue-Sang wrote:
Hey Ashley,
On Oct 21, 2008, at 12:23 AM, Ashley Clark wrote:
I'm pretty sure I've got this worked out and it seems to be
working, BUT I thought that before and when I turned on Auto
Arrange Content on my NSArrayController's this bug popped up. So I
wanted to make sure I'm doing this right.
I'm lazily initializing objects that are being read from a
database, similar to CoreData faulting. In my RMDatabaseObject
class I've implemented a willAccessValueForKey: method that reads
in data from the database if necessary. This method is being called
at the beginning of my willChangeValueForKey: and
willChangeValueForKey:withSetMutation:usingObjects: methods.
Originally, for every property that was being set through the
willAccessValue method I was calling the willChange/didChange
methods and it seemed to work well. At least until I turned on auto-
arrange content on some array controllers. After that I started
getting exceptions stating that observer's were being removed more
times than they had been added on seemingly random key paths.
I finally found a comment by mmalc and seconded by Ronzilla at http://theocacao.com/comment/4423
that seems to indicate that one should NEVER post change
notifications when doing this sort of lazy-loading.
1) Don't send the KVO notification from inside an accessor.
2) Don't change what the result of the accessor would be without
sending a KVO notification.
I guess thing 2 sounds like it contradicts thing 1, but it really
doesn't.
If the object were uninitialized, the return value would be some
uninitialized value. You never return an uninitialized value tho, so
you're not violating 2 by adhering to 1 for the kinda-special case
of lazy accessors.
I guess I'm only seconding my own statement, with an attempt at
explaining it differently.
Here's one: implementing MyObject's foo to return [[self
someToManyRelationshipCollection] objectAtIndex:randomInteger] and
then observing myObject.foo.property would be bad. The result of foo
changes every time you ask for it. From what I remember in my
electrical engineering days, this is one of those hand-waving things
we used to do when doing calculations. "We don't care what the
values were before time t0. We're only interested in the value from
time t0 onward."
Here, we don't care what the value backing the foo accessor was
before we started observing foo. But, we'll want to know what the
value of foo is as soon as we start observing foo - so you don't
need to say you changed foo. For KVO, we wouldn't know what foo
changed from until after the initial access of foo which we're
talking about. After that we'll track new values as time goes by
using will/did change and all will be Good™.
Let me know if I'm still not being clear. Or if I'm answering the
wrong question.
No, that makes perfect sense to me. And after reading the comment at
theocacao it all just kind of clicked that, duh, obviously I don't
need to send notifications that things are being set since from the
perspective of any other class, they could have been set from the very
start. I was just being overly cautious by wrapping every thing via
willChange/didChange when in this instance it turns out I shouldn't
have been.
Anyway, mostly I just wanted to make sure that I was interpreting the
comments correctly. Since I've changed my code to not issue
notifications in this case KVO seems to be working happily 100% of the
time!
Ashley
_______________________________________________
Cocoa-dev mailing list (email@hidden)
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:
This email sent to email@hidden