KeyPath Trick

I'm still on Objective-C but I like the idea of swift having the #keyPath(property name) String-Expression. Less can go wrong and autocompletion and refactoring also works.

In good old Objective-C we only have @selector doing similar things, but nothing that works with key paths. So here is a little trick that I use to fix this problem in my code. First I define this macro:

#define keyPath(k) YES ? @#k : (k ? @"": nil)

Actually the @#k part is already doing the job, but refactoring and autocompletion does not work, if the argument isn't also treated as an expression, therefore I added the little ?: dance.

Now you can use it like this:

[self valueForKeyPath:keyPath(self.sample.greeting)];

It is important also to add the self in front. If self is not appropriate in your situation because you are using the key path from another origin, then use this slightly extended version:

#define keyPathFromObject(o, k) YES ? @#k : ((o ?: o.k) ? @"" : nil)

Once in place it will not be missed on refactoring any more:

image-20180620111144643

Demo code is available as Gist. I'm not the first one having this idea, here and here and here are examples of prior works on the topic.

Update 2018-06-20:

The macro was always evaluating the expression. I modified it to never reach the expression part of the code.

Update 2018-06-21:

The previous implementation did only work for NSString properties, fixed that by adding another ?: round.

Update 2018-06-26:

Haha, I have been blind and reinvented the wheel: This implementation is really nice. They even figured out how to prepend the @ to get @keypath(). I'm happy to see that the implementation is similar although it is full of extra super magic macro power. That said maybe my implementation is still good to take a look at due to it's compactness ;)