Obj-C component-based game architecture and message forwarding - objective-c

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

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!)

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.

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.

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.

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.

Related

Is it possible to change an Objective-C object to a different type at runtime?

I have a situation where I want to create an object before I know what type it will eventually be. I know what its superclass will be, and want to temporarily create a concrete instance of that superclass and allow other objects to use it in that form until its "true" class can be created.
I realize this is pretty crazy and I don't have too high expectations that this is possible, but if I could do this it would be amazing. I know the Obj-C runtime has some pretty powerful features so thought it was at least worth asking.
I've looked into object_setClass, but while this appears to allow you technically change the class of an object at runtime, it doesn't allow you to actually reallocate a new instance, complete with its own ivars, at the address of the original instance, which is really what I need as I don't know specifically what the final class will be (it needs to work with any custom subclass).
Background: My intention is to provide a placeholder object that will allow external code to register dependencies and/or hold a reference to, such that when the object is eventually filled-in, those external dependencies will still hold and they won't have to correct their references.
You could try using NSProxy and ultimately proxying to the "real" underlying object you need.

"Finding" an object instance of a known class?

My first post here (anywhere for that matter!), re. Cocoa/Obj-C (I'm NOT up to speed on either, please be patient!). I hope I haven't missed the answer already, I did try to find it.
I'm an old-school procedural dog (haven't done any programming since the mid 80's, so I probably just can't even learn new tricks), but OOP has my head spinning! My question is:
is there any means at all to
"discover/find/identify" an instance
of an object of a known class, given
that some OTHER unknown process
instantiated it?
eg. somthing that would accomplish this scenario:
(id) anObj = [someTarget getMostRecentInstanceOf:[aKnownClass class]];
for that matter, "getAnyInstance" or "getAllInstances" might do the trick too.
Background: I'm trying to write a plugin for a commercial application, so much of the heavy lifting is being done by the app, behind the scenes.
I have the SDK & header files, I know what class the object is, and what method I need to call (it has only instance methods), I just can't identify the object for targetting.
I've spent untold hours and days going over Apples documentation, tutorials and lots of example/sample code on the web (including here at Stack Overflow), and come up empty. Seems that everything requires a known target object to work, and I just don't have one.
Since I may not be expressing my problem as clearly as needed, I've put up a web page, with diagram & working sample pages to illustrate:
http://www.nulltime.com/svtest/index.html
Any help or guidance will be appreciated! Thanks.
I have the SDK & header files, I know what class the object is, and what method I need to call (it has only instance methods), I just can't identify the object for targetting.
If this is a publicly declared class with publicly declared instance methods (i.e., you have the header for the class and it has instance methods in it), there is probably a way in this application's API to get an instance of the class. Either you are meant to create one yourself, or the application has one (or more) and provides a way to get it (or them). Look at both the header for the class in question and the other headers.
I initially said “there must be a way…”, but I changed it, because there is an alternative reason why the header would have instance methods: The application developer does not intend those instance methods for plug-in use (and didn't mark them appropriately), or did not mean to include that header in the application/SDK (they included it by accident). You may want to ask the application developer for guidance.
If it is not a publicly declared class or its instance methods are not publicly declared, then the application does not support you working with instances of the class. Doing so is a breach of the API contract—not a legal contract, but the expectations that the application has of its plug-ins. If you breach the API contract, you will cause unexpected behavior, either now (not necessarily on your own machine/in your own tests) or in the future.
If the class's public declaration contains only class methods, then perhaps what you're after is not an instance at all—you're supposed to send those messages to the class itself.
This is not possible without having you register each instance in a dictionary as it is created. I.e., override some common factory method at a higher level which does this bookkeeping work. This will fall down when you use delegates that you may not control though, keep that in mind.
I do question the need to even do this at all, but I don't know your problem as well as I perhaps would need to, to recommend a different, more apt way of accomplishing the actual task at hand.
Just as a corollary to the above; I did look at the runtime to see if there was anything that I actually forgot about, but there is not. So my above statement with regards to you requiring to do that bookkeeping yourself, still holds I'm afraid.
Edit:
Based on your diagram (my apologies, just noticed the link after I posted this answer); I would suggest that if you control the classes that are being returned to you, just add a property to them. I.e., add a "name" property that you can set and keep unique. Then just pass the message to each instance, checking whether or not that object is the one you want. It's not particularly clever or anything like that, but it should work for your purposes.

Which object called another object's method in Obj-C

I am looking to write a plugin controller in Cocoa that loads bundles, and exposes a specific set of methods for the plugins to call.
My question is this: is it possible to know (any) info about the object that called a method in the controller. When an instantiated plugin calls a method in my plugin controller, I would like to know which of the plugin instances called the method, without having to rely on the plugin sending a pointer to itself as a parameter (I could always validate the pointer they send, but I want to keep the API methods as simple as possible).
There may be no perfect solution (and there are simple workarounds), but it's always good to learn some new tricks if possible (or the reasons why it's impossible).
Thanks in advance.
It's not possible without walking the stack, and possibly not even then. There's not even a guarantee that a given message was sent from within a method — and even if it was, it may not be the method that you think of as being the "caller." For example, assuming your plugins have access to Cocoa, your controller methods could be called by an NSTimer.
In general, this is not practical. The normal way to accomplish this is to have objects pass themselves around. If you're trying to do this for security reasons, you'll want a much more robust solution anyway, because Cocoa's object model was not designed with that in mind. It's way too easy for objects to lie about who and what they are.
Well, you could throw an exception, catch it and examine its stacktrace.
Assuming that Objective-C supports exceptions, of course.
Sending a reference to the calling object is how this is usually done. As an alternative, you could have your host code provide a proxy object for plugins to talk to. As each plugin is loaded, create a new proxy object for each to talk to.

Abstract design / patterns question

I had a bunch of objects which were responsible for their own construction (get properties from network message, then build). By construction I mean setting frame sizes, colours, that sort of thing, not literal object construction.
The code got really bloated and messy when I started adding conditions to control the building algorithm, so I decided to separate the algorithm to into a "Builder" class, which essentially gets the properties of the object, works out what needs to be done and then applies the changes to the object.
The advantage to having the builder algorithm separate is that I can wrap/decorate it, or override it completely. The object itself doesn't need to worry about how it is built, it just creates a builder and 'decorates' the builder with extra the functionality that it needs to get the job done.
I am quite happy with this approach except for one thing... Because my Builder does not inherit from the object itself (object is large and I want run-time customisation), I have to expose a lot of internal properties of the object.
It's like employing a builder to rebuild your house. He isn't a house himself but he needs access to the internal details, he can't do anything by looking through the windows. I don't want to open my house up to everyone, just the builder.
I know objects are supposed to look after themselves, and in an ideal world my object (house) would build itself, but I am refactoring the build portion of this object only, and I need a way to apply building algorithms dynamically, and I hate opening up my objects with getters and setters just for the sake of the Builder.
I should mention I'm working in Obj-C++ so lack friend classes or internal classes. If the explanation was too abstract I'd be happy to clarify with something a little more concrete. Mostly just looking for ideas or advice about what to do in this kind of situation.
Cheers folks,
Sam
EDIT: is it a good approach to declare a
interface House(StuffTheBuilderNeedsAccessTo)
category inside Builder.h ? That way I suppose I could declare the properties the builder needs and put synthesizers inside House.mm. Nobody would have access to the properties unless they included the Builder header....
That's all I can think of!
I would suggest using Factory pattern to build the object.
You can search for "Factory" on SO and you'll a get a no. of questions related to it.
Also see the Builder pattern.
You might want to consider using a delegate. Add a delegate method (and a protocol for the supported methods) to your class. The objects of the Builder class can be used as delegates.
The delegate can implement methods like calculateFrameSize (which returns a frame size) etc. The returned value of the delegate can be stored as an ivar. This way the implementation details of your class remain hidden. You are just outsourcing part the logic.
There is in fact a design pattern called, suitable enough, Builder which does tries to solve the problem with creating different configurations for a certain class. Check that out. Maybe it can give you some ideas?
But the underlying problem is still there; the builder needs to have access to the properties of the object it is building.
I don't know Obj-C++, so I don't know if this is possible, but this sounds like a problem for Categories. Expose only the necessary methods to your house in the declaration of the house itself, create a category that contains all the private methods you want to keep hidden.
What about the other way around, using multiple inheritance, so your class is also a Builder? That would mean that the bulk of the algorithms could be in the base class, and be extended to fit the neads of you specific House. It is not very beautiful, but it should let you abstract most of the functionality.

Discover subclasses of a given class in Obj-C

Is there any way to discover at runtime which subclasses exist of a given class?
Edit: From the answers so far I think I need to clarify a bit more what I am trying to do. I am aware that this is not a common practice in Cocoa, and that it may come with some caveats.
I am writing a parser using the dynamic creation pattern. (See the book Cocoa Design Patterns by Buck and Yacktman, chapter 5.) Basically, the parser instance processes a stack, and instantiates objects that know how to perform certain calculations.
If I can get all the subclasses of the MYCommand class, I can, for example, provide the user with a list of available commands. Also, in the example from chapter 5, the parser has an substitution dictionary so operators like +, -, * and / can be used. (They are mapped to MYAddCommand, etc.) To me it seemed this information belonged in the MyCommand subclass, not the parser instance as it kinda defeats the idea of dynamic creation.
Not directly, no. You can however get a list of all classes registered with the runtime as well as query those classes for their direct superclass. Keep in mind that this doesn't allow you to find all ancestors for the class up the inheritance tree, just the immediate superclass.
You can use objc_getClassList() to get the list of Class objects registered with the runtime. Then you can loop over that array and call [NSObject superclass] on those Class objects to get their superclass' Class object. If for some reason your classes do not use NSObject as their root class, you can use class_getSuperclass() instead.
I should mention as well that you might be thinking about your application's design incorrectly if you feel it is necessary to do this kind of discovery. Most likely there is another, more conventional way to do what you are trying to accomplish that doesn't involve introspecting on the Objective-C runtime.
Rather than try to automatically register all the subclasses of MYCommand, why not split the problem in two?
First, provide API for registering a class, something like +[MYCommand registerClass:].
Then, create code in MYCommand that means any subclasses will automatically register themselves. Something like:
#implementation MYCommand
+ (void)load
{
[MYCommand registerClass:self];
}
#end
Marc and bbum hit it on the money. This is usually not a good idea.
However, we have code on our CocoaHeads wiki that does this: http://cocoaheads.byu.edu/wiki/getting-all-subclasses
Another approach was just published by Matt Gallagher on his blog.
There's code in my runtime browser project here that includes a -subclassNamesForClass: method. See the RuntimeReporter.[hm] files.