PDA

View Full Version : Proper way for classes to announce their existence




Qaanol
Sep 4, 2013, 04:59 PM
I am writing a simulation program, which will present the user with a list of available simulators to run. Each simulator is implemented as a class, and I want to know the correct way for the program to keep track of the available simulator classes. Ideally the solution should be robust in the case of dynamically-loaded classes.

My first thought is to have a SimulatorManager class which exists as a singleton instance that keeps an NSArray of simulator classes, and have each simulator class implement +load to call [[SimulatorManager sharedInstance] registerSimulator:self]. However, I am not sure if this is the right way to do it, nor if it is even possible to rely on an instance of one class during +load of another.

How should I go about keeping a list of simulator classes known to the application?



gnasher729
Sep 4, 2013, 05:10 PM
Google for "Objective C Runtime", then look for "objc_getClassList" and go from there.

Qaanol
Sep 4, 2013, 05:20 PM
Google for "Objective C Runtime", then look for "objc_getClassList" and go from there.

I can say for sure that I definitely do not want to parse the entire list of classes known to the runtime to populate the list. For starters, it means I would have to parse the list of all classes every time I wanted to check whether the list might possibly need to be updated, which is absurd.

I definitely want the classes to announce their existence in a defined manner, and I am asking for the proper way to implement that.

gnasher729
Sep 4, 2013, 05:33 PM
I can say for sure that I definitely do not want to parse the entire list of classes known to the runtime to populate the list. For starters, it means I would have to parse the list of all classes every time I wanted to check whether the list might possibly need to be updated, which is absurd.

I definitely want the classes to announce their existence in a defined manner, and I am asking for the proper way to implement that.

They all do announce their existence, and the Objective C runtime puts them into the list of all classes. What do you think does the runtime do when you ask for a class by name?

chown33
Sep 4, 2013, 06:00 PM
Ideally the solution should be robust in the case of dynamically-loaded classes.

Dynamic loading under Cocoa is done using bundles.
https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/LoadingCode/Tasks/LoadingBundles.html

Look at the left-hand column in that article. See the "Multi-Bundle Applications" and "Plug-in Architectures" in particular. Also see the Related Documents list.

Found using google search terms:
cocoa bundle loading
which produces some other results that may be useful.

Qaanol
Sep 4, 2013, 06:41 PM
Dynamic loading under Cocoa is done using bundles.
https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/LoadingCode/Tasks/LoadingBundles.html

Look at the left-hand column in that article. See the "Multi-Bundle Applications" and "Plug-in Architectures" in particular. Also see the Related Documents list.

Found using google search terms:
cocoa bundle loading
which produces some other results that may be useful.

Yes I am familiar with Cocoa bundles and had a plug-in architecture in mind when I posted this thread. One way for my application to determine what classes are available in a plug-in is for the principal class of the bundle to keep a hard-coded list of the available classes.

I prefer to avoid a hard-coded solution if I can help it. I would much prefer to have each class announce itself to my code when it is loaded. Is there a viable way to accomplish that result?

chown33
Sep 4, 2013, 06:51 PM
I would much prefer to have each class announce itself to my code when it is loaded. Is there a viable way to accomplish that result?

See the class methods +load and +initialize.

Also see: Dynamic Loading (https://developer.apple.com/library/mac/DOCUMENTATION/Cocoa/Conceptual/ObjCRuntimeGuide/Articles/ocrtDynamicResolution.html).

Google search terms: cocoa class loading


Regardless of the mechanism you use, I suspect you'll need to do a fair amount of testing, trials, and plain old discovery. I strongly doubt you'll find a ready-made or simple solution that does everything you want.

Qaanol
Sep 4, 2013, 07:00 PM
See the class methods +load and +initialize.

Also see: Dynamic Loading (https://developer.apple.com/library/mac/DOCUMENTATION/Cocoa/Conceptual/ObjCRuntimeGuide/Articles/ocrtDynamicResolution.html).

Google search terms: cocoa class loading
Indeed, I believe I specifically mentioned +load in my original post, and asked whether the approach I had in mind using that function was the right way to go.

Regardless of the mechanism you use, I suspect you'll need to do a fair amount of testing, trials, and plain old discovery. I strongly doubt you'll find a ready-made or simple solution that does everything you want.
Perhaps, but I think it is quite likely I may find someone with experience doing the same thing, hence why I posted here.

chown33
Sep 4, 2013, 07:39 PM
Indeed, I believe I specifically mentioned +load in my original post, and asked whether the approach I had in mind using that function was the right way to go.

Whether it's right or not will depend on several things. Inter-class dependencies, for one thing. That's one reason I pointed to bundles, because those are well-defined loadable modules, and finding examples shouldn't be difficult.

Perhaps, but I think it is quite likely I may find someone with experience doing the same thing, hence why I posted here.

The top google result for cocoa class loading is this, which discusses +load, +initialize, etc.
http://www.mikeash.com/pyblog/friday-qa-2009-05-22-objective-c-class-loading-and-initialization.html

Farther down but still on the first page of results:
http://www.cocoawithlove.com/2010/01/getting-subclasses-of-objective-c-class.html

Google has additional results worth looking at. That's why I post the search terms.

Qaanol
Sep 4, 2013, 09:29 PM
Whether it's right or not will depend on several things. Inter-class dependencies, for one thing. That's one reason I pointed to bundles, because those are well-defined loadable modules, and finding examples shouldn't be difficult.


The top google result for cocoa class loading is this, which discusses +load, +initialize, etc.
http://www.mikeash.com/pyblog/friday-qa-2009-05-22-objective-c-class-loading-and-initialization.html

Farther down but still on the first page of results:
http://www.cocoawithlove.com/2010/01/getting-subclasses-of-objective-c-class.html

Google has additional results worth looking at. That's why I post the search terms.
All right, both of those links discuss using +load essentially as I described (although they use factory class methods rather than a singleton instance). Notably though, they both specifically register subclasses with a superclass.

I infer this means it is definitely acceptable for subclasses to register themselves with a superclass. The NSObject documentation mentions that +load is guaranteed to be called for a superclass before any of its subclasses, which seems potentially relevant.

Do we know if it is okay for classes to use +load to register themselves with a class which they do not inherit from?

chown33
Sep 5, 2013, 12:33 AM
Do we know if it is okay for classes to use +load to register themselves with a class which they do not inherit from?

The main constraint that comes to mind is whether the class they wish to register with has itself been +load'ed and +initialize'd. If I had to be certain, I would use plain C (e.g. a linked list, perhaps encapsulated in a function) and sidestep the question of class-load order.

Or write some trial code and see what happens.

Qaanol
Sep 5, 2013, 10:28 AM
The main constraint that comes to mind is whether the class they wish to register with has itself been +load'ed and +initialize'd. If I had to be certain, I would use plain C (e.g. a linked list, perhaps encapsulated in a function) and sidestep the question of class-load order.
Hmm, the NSObject documentation for +load mentions, "In a custom implementation of load you can therefore safely message other unrelated classes from the same image, but any load methods implemented by those classes may not have run yet."

With that, and given that framework classes are guaranteed to have already been loaded and initialized, I suspect that having [SimulatorManager registerSimulator:self] curate a static NSArray might work. I do not need SimulatorManager to implement a +load method, so it does not matter to me if it has been called prior to +registerSimulator:(id)sender.

Or write some trial code and see what happens.
I certainly will, I just wanted to check here because I expect that +load is exactly the sort of place that subtle things could happen sometimes but not others, and I might not notice if things didn't act up at first.