iOS Plugin - applicationDidFinishLaunching

I have a continuous integration environment that builds up the iOS project out of Unity from scratch every time. I am trying to figure out a good way to hook some code into the applicationDidFinishLaunchingWithOptions for initializing some 3rd party plugins. Without keeping the project around on the build server and inserting our own subclass of UnityAppController, I am not finding a good solution.

I looked at the solution posted over at http://www.tinytimgames.com/2011/09/01/unity-plugins-and-uiapplicationdidfinishlaunchingnotifcation/, however this does still not seem to be calling at the appropriate time.

Is there a good method of interjecting your own code into applicationDidFinishLaunching or similar iOS lifecycle events without subclassing, copying over your own appcontroller during postprocessbuildphase or manually having to manage the generated iOS project? Does anyone have experience trying to do something similar?

I use a custom PostprocessBuildPlayer perl script in to add some code to AppController.mm at build time.

Try using a category, as suggested here: http://forum.unity3d.com/threads/82794-Modifying-AppController-from-unity-script-or-plugin

Wouldn’t this mean 2 implementations of the method. I was reading some Apple docs earlier and they said that behaviour is undefined in this case.

Yeah, that’s true. If you’re just initializing things though, you can use one of the other similar-but-not-implemented functions, like applicationWillFinishLaunching.

Or, if you really need to do it in applicationDidFinishLaunching, you can swizzle your own implementation in:

@implementation UnityAppController (YourCategoryForStuff)

+ (void)load {
    Method original, swizzled;
    
    original = class_getInstanceMethod(self, @selector(application:didFinishLaunchingWithOptions:));
    swizzled = class_getInstanceMethod(self, @selector(customApplication:didFinishLaunchingWithOptions:));
    method_exchangeImplementations(original, swizzled);
}

-(BOOL)customApplication:(UIApplication*)application didFinishLaunchingWithOptions:(NSDictionary*)launchOptions {

    // do whatever you need here

    // looks like it's just calling itself, but the implementations were swapped so we're actually 
    // calling the original once we're done 
    [self customApplication:application didFinishLaunchingWithOptions:launchOptions];
}

@end

Then just put your category files in Plugins/iOS and let Unity import it into your project for you.

Nice tip. But how is load() called?

Load gets called automatically as soon as the class gets loaded (before init, even). By swizzling there, you ensure that your implementation will be in place before anything else calls the original method.

So I guess there’s a chance that another implementation of load() could be defined in the original class, and in that case we’re in the same boat as before.

Sort of, but not quite. Load will get called on every category, unlike other methods. See here: http://stackoverflow.com/questions/13326435/nsobject-load-and-initialize-what-do-they-do

In general I think load is rarely implemented, so you’re probably fine to use it. Though, that said, if you have multiple things trying to inject themselves into applicationDidFinishLaunching you’re going to run into issues eventually and have to sort them out yourself no matter what method you use.

Thanks, I’ve learnt something today :slight_smile:

Ah, I wasn’t aware of Objective-C categories. This looks perfect! Thank you both.