How to Set Custom Display Values and Localize NSPredicateEditor

This weekend was my first time ever needing to use NSPredicateEditor in one of my apps. I don’t know who else needs to know this, but just in case…

Maybe the documentation has disappeared online, or maybe it was only ever available via word-of-mouth fifteen years ago, but I lost about four hours the other night trying to figure out how to make the dropdown choices in my NSPredicateEditor show user-friendly names instead their actual key paths.

Here’s what I had…

And here’s what I wanted…

Unlike its parent class NSRuleEditor, NSPredicateEditor doesn’t ask a delgate for display values to use in place of the key paths. I had found arcane whisperings in dark, ancient parts of the web mentioning needing to use the formattingDictionary dictionary property, but for the life of me couldn’t figure out what to do with it.

Only after hitting my head on a wall for half a night did I finally stumble across this twelve year-old cocoa-dev mailing list post on the eighth Google results page behind a bunch of Chinese StackOverflow scraping websites with a solution.

On Oct 28, 2008, at 3:57 PM, Peter Ammon wrote:
Here’s something that may help – there’s a method on NSRuleEditor - (NSData *)_generateFormattingDictionaryStringsFile. It gives you a strings file (as UTF16 data) appropriate for that control – write the data to a .strings file and then you can start translating it.
That method should never be called in production code but it can be useful for generating the strings file.

God bless the Apple engineer that wrote that private API method because it absolutely does what it says on the tin. Add all of your NSPredicateRowTemplates as you would expect using your key paths, call that method, and you get output suitable for dropping into a strings file that NSPredicateEditor will read from and localize itself with. My strings file looks like this…

Here’s the NSPredicateEditor category I added to my project that lets me generate the strings on demand…

You can call it from your Swift code like this…

So, yeah. That took longer than I expected.

Hopefully the absurd amount of SEO keywords I stuffed into this blog post will help future developers find this info now that the old web is disappearing from Google.