iOS Frameworks : Initializing Yourself in 0 Lines of Code

Ease of integration is a priority for every SDK developer. An app developer shouldn’t have to spend hours digging deep into your documentation to accomplish what he or she has set out to do. That said, as an SDK developer you are probably wary of providing an integration that’s too simple, since you want your code to be notified of some important moments in the application lifecycle. One of the most important clues about the app is its initialization status. For instance, you may have critical setup tasks to do at app launch, but you don’t want your integrator to invoke your SDK in their application:DidFinishLaunchingWithOptions: method.

The UIApplication class reference documents some handy notifications that you may not be aware of, such as  “UIApplicationDidFinishLaunchingNotification”, “UIApplicationDidBecomeActiveNotification”, and “UIApplicationDidEnterBackgroundNotification”. These notifications are the key to your SDK receiving information about the application’s initialization status. With them, you can know when the app has finished launching, when it was backgrounded and when its session has resumed.

But handy as these notifications may be, how should your SDK register to observe them in a timely fashion?

NSObject documents the static +load method as being “Invoked whenever a class or category is added to the Objective-C runtime; implement this method to perform class-specific behavior upon loading.”

This is extremely powerful. Since the +load method is invoked once for every new class that is added to the runtime, we now have a way to execute code without ever being called by the integrating developer. However, +load is called extremely early in the application launch cycle. (It’s actually called before the main() function of the application.) At this stage, the app hasn’t really even started yet, so we can’t safely perform any operations here. In fact, we’re still unsure which other classes have received their +load message and are safe to use. Thankfully, Apple did document the initialization procedure:

The order of initialization is as follows:

  1. All initializers in any framework you link to.
  2. All +load methods in your image.
  3. All C++ static initializers and C/C++ __attribute__(constructor) functions in your image.
  4. All initializers in frameworks that link to you.

From this we learn that any frameworks you link to (namely, Apple frameworks) are loaded before your classes. That makes Apple framework classes safe to use. This is the perfect place for you to register with NSNotificationCenter. Note that at this point there is still no autorelease pool, so make sure to use one (even if you’re using ARC):

 +(void)load
 {
   @autoreleasepool {
     [[NSNotificationCenter defaultCenter] addObserver:self
     selector:@selector(applicationDidFinishLaunching:)
     name:UIApplicationDidFinishLaunchingNotification
     object:nil];

     [[NSNotificationCenter defaultCenter] addObserver:self
     selector:@selector(applicationDidBecomeActive:)
     name:UIApplicationDidBecomeActiveNotification
     object:nil];

     [[NSNotificationCenter defaultCenter] addObserver:self
     selector:@selector(applicationDidEnterBackground:)
     name:UIApplicationDidEnterBackgroundNotification
     object:nil];
   }
 }

Now that you’ve registered as an observer with NSNotificationCenter, you can implement methods to receive these notifications and safely perform any setup and/or cleanup code you need, without the developer ever needing to call into your SDK:

+(void)applicationDidFinishLaunching:(NSNotification*)notification

{

}

+(void)applicationDidBecomeActive:(NSNotification*)notification

{

}

+(void)applicationDidEnterBackground:(NSNotification*)notification

{

}

Note that these notifications are fired after their respective methods have completed in the app’s UIApplicationDelegate.

That’s it! You’ve just successfully initialized your SDK with 0 lines of code required from the developer. For some SDKs, the developer may never need to call you. How fantastic is that?

Check out my github for a working sample.

Further reading on the +load method from the inimitable Mike Ash: https://www.mikeash.com/pyblog/friday-qa-2009-05-22-objective-c-class-loading-and-initialization.html



Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.