Re: Doesn't -willChangeValueForKey: copy the value before I change it?
Re: Doesn't -willChangeValueForKey: copy the value before I change it?
- Subject: Re: Doesn't -willChangeValueForKey: copy the value before I change it?
- From: Jerry Krinock <email@hidden>
- Date: Sat, 15 Dec 2007 19:59:03 -0800
On 2007 Dec, 15, at 17:41, Chris Hanson wrote:
On Dec 14, 2007, at 5:58 PM, Jerry Krinock wrote:
I've implemented a KVO-compliant NSMutableSet instance variable.
It has this little mutator:
Either way, the observer gets notified, but if I DO_IT_MY_WAY, the
"old" value in the notification is wrong; it is the same as the
"new" value. My mental picture is that -willChangeValueForKey: is
invoked to copy the "old" value immediately before a change. But
it looks like maybe I'm wrong.
Can someone please explain, at a little higher level, what's wrong
with my picture?
I think it's your expectation that the old value is being copied
that's wrong. Key-Value Observing needs to work with an instance of
any subclass of NSObject, not just those that conform to
<NSCopying>, so it can only really retain.
Ah, very sensible explanation.
It looks like I'd been reading too much of the deeper documentation
which focuses on special applications that require things like manual
KVO. I believe that the other KVC compliance methods mentioned by
Dave are more than I need (and also may be only applicable to
NSManagedObjects).
With these improvements, I get the more precise change info that Dave
mentioned, kind=NSKeyValueChangeRemoval.
Thanks, guys!
Jerry
********* IMPROVED CODE ***************
/* Improved code demonstrating automatic KVO by using
mutators with KVC-standard method names. */
#import <Foundation/Foundation.h>
#pragma mark Observee Class
@interface Observee : NSObject {
NSMutableSet* _stuffs ;
}
@end
@implementation Observee
- (NSMutableSet *)stuffs {
return _stuffs;
}
// Mutators with names in standard KVC format that
// automatically trigger KVO observations
- (void)setStuffs:(NSMutableSet *)newStuffs {
[newStuffs retain];
[_stuffs release];
_stuffs = newStuffs;
}
- (void)addStuffsObject:(id)newStuff {
[[self stuffs] addObject:newStuff];
}
- (void)removeStuffsObject:(id)newStuff {
[[self stuffs] removeObject:newStuff];
}
// Higher-level mutator
// Note that it invokes a lower-level KVC-standard mutator
- (void)deleteOneStuff {
[self removeStuffsObject:[[self stuffs] anyObject]] ;
}
@end
#pragma mark Observer Class
@interface Observer : NSObject {
}
@end
@implementation Observer
- (void)observeValueForKeyPath:(NSString *)keyPath
ofObject:(id)object
change:(NSDictionary *)change
context:(void *)context {
NSLog(@"Observer observed change:\n%@", change) ;
}
@end
#pragma mark Main
int main (int argc, const char * argv[]) {
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
Observer* observer = [[Observer alloc] init] ;
Observee* observee = [[Observee alloc] init] ;
[observee addObserver:observer
forKeyPath:@"stuffs"
options:(NSKeyValueObservingOptionOld |
NSKeyValueObservingOptionNew)
context:NULL] ;
[observee setStuffs:[NSMutableSet setWithObjects:@"stuff1",
@"stuff2", @"stuff3", nil]] ;
[observee deleteOneStuff] ;
[pool release] ;
return 0;
}
******* CONSOLE OUTPUT *********
2007-12-15 19:22:02.317 KVODemo[24567:10b] Observer observed change:
{
kind = 1;
new = {(
stuff1,
stuff3,
stuff2
)};
old = <null>;
}
2007-12-15 19:22:02.338 KVODemo[24567:10b] Observer observed change:
{
kind = 3;
old = {(
stuff1
)};
}
_______________________________________________
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