Ray Pendergraph Ray Pendergraph - 1 year ago 40
Objective-C Question

Bulding property paths programatically with another class's selectors. How does this work?

I have a method I that takes a variable number of

values and returns a proper NSString I found on this site a while back. This is useful when building property paths for me because I don't like the idea of using strings for this and like the idea of the compiler being able to check the values the path is built from. The method is:

+(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)];


return [keys componentsJoinedByString:@"."];

This works beautifully but the question is: Why? If I have property on my current object named
and it has a
the path would be
obviously and the call to my method would look like:

+(NSSet *)keyPathsForValuesAffectingFoo
return [NSSet setWithObject:[self keyPathFromSelectors:@selector(person), @selector(name),nil]];

selector is (should not) technically visible in my current class, it's in the
class to which I have a reference so how am I accessing the correct
SEL object?

Answer Source

Selectors are do not carry the guarantee that the method actually exists on the object in question. You can get compiler warnings that a selector name doesn't exist anywhere, but you won't get assurance that it does exist on the object it will be used on. For example, this compiles:

[person performSelector: @selector(applicationDidBecomeActive:)]

Even though applicationDidBecomeActive exists on your app delegate and not person.

However! This kind of thing is possible through compiler macros. Look at the libextobjc library which provides exactly the kind of selector/key path compile time checking you're looking for. This is what powers a lot of the keypath magic in ReactiveCocoa but it can also be used standalone.