Lets say I have a custom control called FooBox. It is just a square on the screen. It has some properties like color, border, etc. When I change the properties, I want the FooBox to redraw itself to reflect its new properties. Is there a way to do that without writing custom setters and putting [self setNeedsDisplay:YES] into all of them?
Two other ways:
- Have whatever is sending the view the accessor message send
setNeedsDisplay:YES
to it immediately after. Not always possible, and no less of a hassle. - Override
setValue:forKey:
to add thesetNeedsDisplay:
message to it, and use that to set the view's properties. This will require boxing up any numeric or structure values, which is trading one hassle for another.
So, effectively, no.
I'm not aware of one. I'd write myself a few macros to do the trick if it bothered me enough.
EDIT: Peter is right in the comments, this solution only works if there is an observer registered for that property. I remember now that I had done this on a CALayer with @dynamic properties, in which case this works as you would like. In the general case though, this is not a good solution to your problem.
Assuming your class is KVC compliant for the properties which you want to trigger a redisplay, I would override the -didChangeValueForKey:
method to call [self setNeedsDisplay]
when the key matches one of your properties. I think this is slightly better than Peter's method of overriding -setValue:forKey: because it does not get in the way of the normal KVC machinery and doesn't require the boxing that he mentions.
- (void)didChangeValueForKey:(NSString*)key {
if ([@"propertyOne" isEqualToString:Key] ||
....) {
[self setNeedsDisplay];
}
[super didChangeValueForKey:key]; // <- Don't forget this
}
I am not certain if this is the right way to do it, but you could consider using NSKeyValueObserving
and register the object as observer of itself, and do the redrawing in the -observeValueForKeyPath:ofObject:change:context:
method.