Lets say that I have:
@property NSNumber* number;
And my controller is observing:
- (void)observeValueForKeyPath:(NSString *)keyPath ...
{
if ([keyPath isEqualToString:@"number"]) ...
}
My question is - whats your approach to refactoring the name of number
property?
It's obvious that I need to update observed key in observers code, but how could I do it in some smart/automatic way, and dont miss any observer watching to handle the change of my property?
One way is to declare string constants for all the properties which are being observed. Use these constants for adding observer and comparing keypath
. You should change the value of those string constants whenever you want to rename the property.
I dont think that complete atomisation is possible.
Ok, I'll respond to myself:) My solution is a mix of Apurv solution and unit testing.
Here it is:
1 For each observed property in MyClass
define:
static NSString* MyClassPropertyNameNumber = @"number";
2 In - (void)observeValueForKeyPath:(NSString *)keyPath ...
implementation use only defined NSStrings.
- (void)observeValueForKeyPath:(NSString *)keyPath ...
{
if ([keyPath isEqualToString:MyClassPropertyNameNumber]) ...
}
3 Write the unit test which will check if MyClass object responds to setNumber:
and number
selectors.
- (void)testMyClass
{
SEL numberGetter = NSSelectorFromString(MyClassPropertyNameNumber);
SEL numberSetter = NSSelectorFromString([NSString stringWithFormat:@"set%@:", MyClassPropertyNameNumber]);
MyClass* testMyClass = [[MyClass alloc] init];
if (![testMyClass respondsToSelector:numberGetter] || ![testMyClass respondsToSelector:numberSetter])
{
STFail(@"%@: %@ property name has changed! Please update your defined property name!", NSStringFromClass([MyClass class]), MyClassPropertyNameNumber);
}
}
It will fail if you'll change property name, and dont update defined property name.
I hope it will be helpful for someone:)
Define a variable for each observed key path, use them as contexts when registering and in the observer handler method:
static void * numberKVO = &numberKVO;
static void * letterKVO = &letterKVO;
...
[self addObserver:self
forKeyPath:@"kp.4.number"
options:NSKeyValueObservingOptionNew
context:numberKVO];
[self addObserver:self
forKeyPath:@"kp.4.letter"
options:NSKeyValueObservingOptionNew
context:letterKVO];
...
- (void) observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
if (context == numberKVO) {
...
} else if (context == letterKVO) {
...
}
}
You can modify the properties and key paths without changing anything else.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With