Reputation: 1152
When registering to observe an object via KVO I write this code to avoid hardcoded strings:
[myObject addObserver:self
forKeyPath:NSStringFromSelector(@selector(myProperty))
options:NSKeyValueObservingOptionInitial | NSKeyValueObservingOptionNew
context:NULL];
Note the NSStringFromSelector. It protects me at compile-time in the event that I change the name of myProperty and forget I had something observing it.
But the situation is more complicated when using nested properties, e.g., "myProperty1.myProperty2"
My naive solution is to use macros like the following:
#define KEYPATHSTRING1(a) NSStringFromSelector(@selector(a))
#define KEYPATHSTRING2(a, b) [NSString stringWithFormat:@"%@.%@", NSStringFromSelector(@selector(a)), NSStringFromSelector(@selector(b))]
#define KEYPATHSTRING3(a, b, c) [NSString stringWithFormat:@"%@.%@.%@", NSStringFromSelector(@selector(a)), NSStringFromSelector(@selector(b)), NSStringFromSelector(@selector(c))]
Any better or standardized solutions out there? Searches on Google and SO turned up nothing for me that addressed this particular question.
Upvotes: 4
Views: 500
Reputation: 35022
Swift 3 adds #keyPath()
to generate a key path string from a "property chain".
let keyPathString = #keyPath(MyType.myProperty1.myProperty2)
The tokens inside the function are not Strings and will be checked by the compiler.
Upvotes: 0
Reputation: 119031
I haven't tried this (or even compiling it), but you could look at using a variadic helper method:
+ (NSString *)keyPathFromSelectors:(SEL)firstArg, ...
{
NSMutableArray *keys = [NSMutableArray array];
va_list args;
va_start(args, firstArg);
for (SEL arg = firstArg; arg != nil; arg = va_arg(args, SEL))
{
[keys addObject:NSStringFromSelector(arg)];
}
va_end(args);
return [keys componentsJoinedByString:@"."];
}
Upvotes: 2
Reputation: 515
I use EXTKeyPathCoding.h from libextobjc. You can check how they do same at https://github.com/jspahrsummers/libextobjc/blob/master/extobjc/EXTKeyPathCoding.h
Upvotes: 1