So, I think you might think that “never climbing” the hierarchy is too literal.
I think the idea is that you don’t know exactly what a parent is, but you can define a protocol and know that regardless of your parent, it responds to the specified protocol. You ideally check the code to confirm that it responds to this protocol. Then use the protocol to send the message in a general way, in which you pass the coin object to the parent object and allow the parent object to animate it from the screen and in the HUD.
Subcontrollers then have an instance variable id<parent_protocol> parent; , and their initialization method takes one of them as a parameter. Given your description, you already have something like this in place, or at least enough to implement, "subcontrollers, as a rule, are not aware of their neighboring controllers and use the methods in the main controller to interact with them," as you say it.
So the idea from a design point of view is that a coin acceptor appears on the display panel, and all he knows is that the parent object has a pickupCoin: method that will do what works with the selected coin. The display panel does not know that it goes to the HUD or anything else, the coins just collected are processed by the pickupCoin: parent controller pickupCoin: .
OOP design philosophy is that all parent knowledge is encapsulated in a protocol definition. This makes the child and the parent more loosely coupled so that you can swap any parent who has implemented this protocol, and the children will still work fine.
There are more loose connections that you could use (for example, notifications posted on a global scale), but in the cases when you are describing, I think that something like what I have indicated is probably more appropriate and, probably more productive.
Does it help?
source share