Why do I receive KVO notifications when a key is set to the same value that it already is?

This happens not only when the new and old values are -isEqual:, but when they are identically the same pointer. I can't think of any reason why anyone would want notification of a no-op.

I understand that it's easy enough to filter these out in my observer methods, but it's certainly a waste of CPU cycles. I wonder if maybe Apple calculated that, in their implementation, it is on average less CPU cycles for me to filter them out in the notifications I actually receive, as compared to Cocoa filtering all notifications before posting?

I presume that, for example, Cocoa's NSControl subclasses must all be checking for equality before redrawing in responding to a KVO notification?

Jerry Krinock

******* Console Output **********

[Session started at 2009-07-08 14:51:07 -0700.]
2009-07-08 14:51:07.678 KVO triggered by change:
{
    kind = 1;
    new = alpha;
    old = <null>;
}
2009-07-08 14:51:07.746 KVO triggered by change:
{
    kind = 1;
    new = beta;
    old = alpha;
}
2009-07-08 14:51:07.752 KVO triggered by change:
{
    kind = 1;
    new = beta;
    old = beta;
}
2009-07-08 14:51:07.760 KVO triggered by change:
{
    kind = 1;
    new = gamma;
    old = beta;
}
2009-07-08 14:51:07.761 KVO triggered by change:
{
    kind = 1;
    new = gamma;
    old = gamma;
}
2009-07-08 14:51:07.764 KVO triggered by change:
{
    kind = 1;
    new = delta;
    old = gamma;
}

The Debugger has exited with status 0.


******* Demo Code **********

#import <Cocoa/Cocoa.h>


@interface Foo : NSObject {
    NSString* name ;
}

@property (copy) NSString* name ;

@end

@implementation Foo

@synthesize name ;

@end


@interface Observer : NSObject {
    id observee ;
}

@property (retain) id observee ;

@end

@implementation Observer

@synthesize observee ;


- (id)initWithObservee:(id)observee_ {
    self = [super init] ;
    if (self != nil) {
        [self setObservee:observee_] ;
        [observee addObserver:self
                   forKeyPath:@"name"
                      options:(NSKeyValueObservingOptionOld
                               + NSKeyValueObservingOptionNew)
                      context:NULL] ;
    }
    return self ;
}


- (void)observeValueForKeyPath:(NSString *)keyPath
                      ofObject:(id)object
                        change:(NSDictionary *)change
                       context:(void *)context {
    NSLog(@"KVO triggered by change:\n%@", change) ;
}


- (void) dealloc {
    [observee removeObserver:self
                  forKeyPath:@"name"] ;
    [observee release] ;

    [super dealloc] ;
}

@end


int main (int argc, const char * argv[]) {
    NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init] ;

    Foo* foo = [[Foo alloc] init] ;

    Observer* observer = [[Observer alloc] initWithObservee:foo] ;

    NSString* alpha = @"alpha" ;
    NSString* beta = @"beta" ;
    NSString* gamma = @"gamma" ;
    NSString* delta = @"delta" ;

    [foo setName:alpha] ;
    [foo setName:beta] ;
    [foo setName:beta] ;
    [foo setName:gamma] ;
    [foo setName:gamma] ;
    [foo setName:delta] ;

    [foo release] ;
    [observer release] ;

    [pool release] ;
}


_______________________________________________

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

Reply via email to