Doesn't -willChangeValueForKey: copy the value before I change it?
Doesn't -willChangeValueForKey: copy the value before I change it?
- Subject: Doesn't -willChangeValueForKey: copy the value before I change it?
- From: Jerry Krinock <email@hidden>
- Date: Fri, 14 Dec 2007 17:58:30 -0800
I've implemented a KVO-compliant NSMutableSet instance variable. It
has this little mutator:
- (void)deleteSomeStuff {
[self willChangeValueForKey:@"stuffs"] ;
#ifdef DO_IT_MY_WAY
[_stuffs removeObject:[_stuffs anyObject]] ;
#else
NSMutableSet* newStuffs = [_stuffs mutableCopy] ;
[_stuffs release] ;
[newStuffs removeObject:[newStuffs anyObject]] ;
_stuffs = newStuffs ;
#endif
[self didChangeValueForKey:@"stuffs"];
}
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?
Jerry
******** DEMO PROJECT CODE ********
//#define DO_IT_MY_WAY
#import <Foundation/Foundation.h>
#pragma mark Observee Class
@interface Observee : NSObject {
NSMutableSet* _stuffs ;
}
@end
@implementation Observee
+ (BOOL)automaticallyNotifiesObserversForKey: (NSString *)theKey {
BOOL automatic;
if ([theKey isEqualToString:@"stuffs"])
automatic = NO;
else
automatic = [super
automaticallyNotifiesObserversForKey:theKey];
return automatic;
}
- (NSMutableSet *)stuffs {
return _stuffs;
}
- (void)setStuffs:(NSMutableSet *)newStuffs {
[newStuffs retain];
[_stuffs release];
[self willChangeValueForKey:@"stuffs"];
_stuffs = newStuffs;
[self didChangeValueForKey:@"stuffs"];
}
- (void)deleteSomeStuff {
[self willChangeValueForKey:@"stuffs"] ;
#ifdef DO_IT_MY_WAY
[_stuffs removeObject:[_stuffs anyObject]] ;
#else
NSMutableSet* newStuffs = [_stuffs mutableCopy] ;
[_stuffs release] ;
[newStuffs removeObject:[newStuffs anyObject]] ;
_stuffs = newStuffs ;
#endif
[self didChangeValueForKey:@"stuffs"];
}
@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 deleteSomeStuff] ;
[pool release] ;
return 0;
}
********** CONSOLE OUTPUT IF DO_IT_MY_WAY ************
2007-12-14 17:33:17.606 KVODemo[20028:10b] Observer observed change:
{
kind = 1;
new = {(
stuff1,
stuff3,
stuff2
)};
old = <null>;
}
2007-12-14 17:33:17.609 KVODemo[20028:10b] Observer observed change:
{
kind = 1;
new = {(
stuff3,
stuff2
)};
old = {(
stuff3,
stuff2
)};
}
********** CONSOLE OUTPUT IF NOT DO_IT_MY_WAY ************
2007-12-14 17:44:07.246 KVODemo[20093:10b] Observer observed change:
{
kind = 1;
new = {(
stuff1,
stuff3,
stuff2
)};
old = <null>;
}
2007-12-14 17:44:07.249 KVODemo[20093:10b] Observer observed change:
{
kind = 1;
new = {(
stuff3,
stuff2
)};
old = {(
stuff1,
stuff3,
stuff2
)};
}
_______________________________________________
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