0

Is there a standard mechanism with Objective C and the iOS runtime to register setup code?

Why?

The advantage of this is that you can decouple your code nicely.

  • If a subsystem needs particular setup, the set up stays in that subsystem.

  • If a group of files need to register that they should all be offered as a particular service, that can be encapsulated in individual files that offer the service and there is no need for a separate configuration file to be kept up to date.

Getting the code to run isn't especially important – I can do that myself with various entry points. What I need is for the compiler or linker or run time or magic to be able to collect up anything that I've registered in different parts of a program, and let me have it when I need it.

How to in c++

With c++, I've typically arranged for this with static instances that are constructed before main() is called. I could use objective-c++, but I'd much prefer to use a standard mechanism.

Thanks.

Community
  • 1
  • 1
Benjohn
  • 13,228
  • 9
  • 65
  • 127
  • There is "class init" method that can be declared to be called on the first reference to a class. I forget what the syntax is, though. – Hot Licks May 08 '14 at 16:43
  • 2
    possible duplicate of [NSObject +load and +initialize - What do they do?](http://stackoverflow.com/questions/13326435/nsobject-load-and-initialize-what-do-they-do) – rob mayoff May 08 '14 at 16:45
  • Interesting, thanks – neither of these options look great from the description [here](https://www.mikeash.com/pyblog/friday-qa-2009-05-22-objective-c-class-loading-and-initialization.html). `load` is very early on, and `initialise` is lazy, so won't cause creation of a class otherwise unreferenced (which is primarily the kind of mechanism I'm after). – Benjohn May 08 '14 at 16:48
  • You can use a static instance of a C++, if you want. You can mix C++ and Objective-C in the same file (it's called Objective-C++) by giving the file a `.mm` suffix. – rob mayoff May 08 '14 at 16:49
  • Thanks @robmayoff – as I mentioned, I would prefer to avoid objective c++. – Benjohn May 08 '14 at 16:51
  • Why don't you think Objective-C++ is a standard mechanism? The Objective-C runtime is written in Objective-C++ (as are other parts of the system like Core Animation). – rob mayoff May 08 '14 at 16:52
  • @robmayoff From the linked answer, it looks like `load` is safer than the article I read suggests, so I think I'll explore that. `initialize` looks very useful, but not specifically in this case where classes would otherwise be unreferenced, so never lazily initialized. – Benjohn May 08 '14 at 16:53
  • @robmayoff Heh, I've always felt it was a bit of a second class citizen (I've used it quite a bit in the past). I didn't know about runtime and core animation – interesting. I always seem to need to rename great swathes of files to `.mm` (like an infection), which isn't a brilliant objection! :-) – Benjohn May 08 '14 at 16:58
  • @robmayoff Incidentally, is there a correct thing to do if a question is a duplicate? – Benjohn May 08 '14 at 16:59
  • I don't know if there's a way for you to close your own question as a dup. – rob mayoff May 08 '14 at 20:08

2 Answers2

2

I would look up:

+ (void)initialize

This method is called whenever a message is first sent to the class meta-object, such as, for example, when alloc-ing an object of that class.

David Doyle
  • 1,716
  • 10
  • 23
  • Thanks – while very useful to know about (thanks), `+(void) initialize` is lazily called on first use of a class. As classes needing to register themselves may be otherwise unreferenced in a code base, it's not useful here. However, the `+(void) load` method should do the trick. – Benjohn May 08 '14 at 16:55
  • Had a fairly similar issue myself with wanting to register that a class was available to handle a particular context - never found a nice solution, I'm afraid I just went with adding a lot of the registration very early in the app's lifecycle. Sorry I can't offer more insight! – David Doyle May 08 '14 at 17:00
  • :-) My frequent approach, also. But it's nearly Friday afternoon, so I thought I'd try to get it right this time. – Benjohn May 08 '14 at 17:02
0

Registering Code

Use the class method +(void) load for components that need to self register themselves.

Note that the load method is run on all subclasses and all categories. This is nothing like the the normal method calling behaviour.

Creating a Registry

If components need to register themselves in some kind of container, use the class method +(void) initialise to create a container to hold the components that are going to register themselves. It seems from my limited testing that initialize can be called before load when a load method uses a class with an initialize method, which is pretty cool if reliable.

Running Registered Code

If the components should do something at some specific entry point of your App, then at that entry point, grab the registered components from the registry and do that thing. Eg, you might extend you UIApplicationDelegate's -(BOOL) application:didFinishLaunchingWithOptions: to actually perform the setup stages the components registered.

In my case, I actually want the registered code to get run every time a specific kind of object is constructed, so I call the registered methods there and let them have the object being constructed.

More references on load and initialise

Thank you for the answers and comments that let me put this answer together.

Community
  • 1
  • 1
Benjohn
  • 13,228
  • 9
  • 65
  • 127