Almost every programmer has been there. You've created a beautifully architected application with each class fitting perfectly into well defined boundaries. Then you hit a snag, you need to pollute your nice clean architecture and destroy one of those boundaries to get something to work (or face a huge amount of code to get it to fit in with your existing system).
I hit this problem with Lighthouse Keeper and found a rather nice solution to it. When talking to Lighthouse I have a single "smart" class that deals with all API calls, which then creates a bunch of "dumb" data objects that handle storage and saving (eg Tickets, Milestones, Projects, etc). These data objects contain integer ids when they need to reference other types of data object, and the "smart" controller class has methods to make perform the task of linking these together if I need them (eg getting all the milestones in a certain project).1
But of course this approach leads to issues, the biggest of which I found was sorting. Cocoa provides a very nice class for sorting called NSSortDescriptor. You set a key, whether it is ascending or descending and optionally a selector to call on the object to compare them. Now, when sorting tickets by milestones or users, you want to sort by the milestone name or the user's name not their id. The problem is, there is no way to move from a ticket to a milestone with key value coding the way I've set things up.
So I'm stuck with a dilemma. I can either pollute my nice cleanly architected code by letting tickets know about other objects, or I can keep my clean architecture but write my own sorting code (but due to the way table views work it is a bit more complicated than that). Well thankfully, I found a way to both have my cake and eat it and it involved categories.
By creating a category on my tickets class, I could add methods that referenced other objects, while having my actual ticket class be completely and utterly oblivious to the other objects. I could now create a simple KVC to sort my tickets "milestone.name". As always, it's frustrating how incredibly simple and obvious a solution seems once you've found it, but I'm surprised that nobody seems to have posted about this before.