views:

60

answers:

5

Hello,

I've been trying to implement a simple component-based game object architecture using Objective-C, much along the lines of the article 'Evolve Your Hierarchy' by Mick West. To this end, I've successfully used a some ideas as outlined in the article 'Objective-C Message Forwarding' by Mike Ash, that is to say using the -(id)forwardingTargetForSelector: method.

The basic setup is I have a container GameObject class, that contains three instances of component classes as instance variables: GCPositioning, GCRigidBody, and GCRendering. The -(id)forwardingTargetForSelector: method returns whichever component will respond to the relevant selector, determined using the -(BOOL)respondsToSelector: method.

All this, in a way, works like a charm: I can call a method on the GameObject instance of which the implementation is found in one of the components, and it works. Of course, the problem is that the compiler gives 'may not respond to ...' warnings for each call. Now, my question is, how do I avoid this? And specifically regarding the fact that the point is that each instance of GameObject will have a different set of components? Maybe a way to register methods with the container objects, on a object per object basis? Such as, can I create some kind of -(void)registerMethodWithGameObject: method, and how would I do that?

Now, it may or may not be obvious that I'm fairly new to Cocoa and Objective-C, and just horsing around, basically, and this whole thing may be very alien here. Of course, though I would very much like to know of a solution to my specific issue, anyone who would care to explain a more elegant way of doing this would additionally be very welcome.

Much appreciated, -Bastiaan

A: 

A simple way to have those warnings disappear would be to declare the instance variables of type id

That way the compiler assumes you know what you're doing regarding the type of the object and that the object will respond to whatever messages you send to it, or if it doesn't you don't care.

Ben S
A: 

Override your GameObject's -respondsToSelector: method. Your implementation should in turn send a respondsToSelector: message to each of its instances, and return YES if any one of them returns YES.

jlehr
...and of course, use `id` as the data type, as others have suggested.
jlehr
A: 

You can use type of id - or you could invoke the methods using performSelector methods, or create an NSInvocation if the arguments are complex. This is all just a way of getting around compiler warnings, however. If your objects respond to several methods, then possibly declaring a protocol might help, although the same caveat applies.

Paul Lynch
A: 

I don't think that sending the container object all of its components' messages is what Mick West was suggesting--that doesn't help to remove the idea of a "monolithic game entity object".

The eventual goal is to have the components communicate directly with one another, with no container object at all. Until then, the container object acts as glue between old code that expects a single object for each game entity and the new component-to-component system.

That is, you shouldn't need to use message forwarding at all in the final product, so ignoring the warnings, or declaring variables as id for now to quiet them, isn't all that ugly. (The plan as laid out by the article is to eventually remove the very code that is causing your warnings!)

andyvn22
A: 

Another option if I understand the problem correctly is to implement a protocol. This is link an interface in java and variables can be declared like this:

id anObjectRef

That way the compiler understands that the object referred to by anObjectRef conforms to the protocol.

There are also methods that can tell you if an particular object conforms to a specific protocol before you cast or assign it.

Derek Clarkson