I'm not aware of a really good way to do this, but the brute force approach works pretty well.
In effect, you create a custom cell subclass, put the action method for the long press in the subclass, then inject a reference to the view controller into every cell you return when the table view asks you for one. The action method in the cell subclass just calls through to the view controller.
In practice, what you'd actually do is treat the view controller as a cell delegate. You would create a protocol with the method that the cell's action message invokes, and conform the view controller to the protocol.
You also need to make the cell "know" which item in the data source it represents, and add that to the passed-through call, if the view controller needs to know which cell had the long press.
Why is this so hard? Because the target-action mechanism was originally designed for the responder chain. Events can cause a search up the responder chain, looking for a target that will accept a certain action, but this breaks down when the item "detecting" the event is not ever made the first responder.
That's true of this case. The cell is a view that typically isn't first responder, but it's where the long press action is initially presented. That means you have to route your long press manually.
(One gotcha to be careful of is to avoid having your cell spontaneously call into its delegate, in situations other than when the call is triggered by a user action. That's because the cell doesn't know when it's no longer *in* the table view, and is instead just sitting in a queue of available cells.)