Reputation: 6181
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?
Upvotes: 5
Views: 290
Reputation: 6181
Mogenerator is a great tool when it comes to deal with Core Data model classes. It generates NSStrings for all attributes, relationships, and fetched properties in:
extern const struct ModelClassAttributes
extern const struct ModelClassRelationships
extern const struct ModelClassFetchedProperties
Upvotes: 0
Reputation: 19641
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.
Upvotes: 1
Reputation: 6181
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:)
Upvotes: 3
Reputation: 17186
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.
Upvotes: 3