I need to add some code to application:didFinishLaunchingWithOptions:
in UnityAppController
that configures Google AdWords Conversion Tracking using their Objective-C SDK.
Editing this file manually each time Unity generates the Xcode project seems error prone, so I'm thinking about adding a post build step using the PostProcessBuild
attribute that would apply a patch for generated Unity code.
However, patch files are hard to maintain so I'm looking for alternative solutions. It seems that subclassingUnityAppController
via the IMPL_APP_CONTROLLER_SUBCLASS
macro and overriding application:didFinishLaunchingWithOptions:
there can be one of them.
But after I do this another third party plugin (Google Play Games) that also subclasses UnityAppController
using the same method stops working because its app controller is no longer called. Here is a relevant piece of code from that plugin:
@interface GPGSAppController : UnityAppController {
}
@end
IMPL_APP_CONTROLLER_SUBCLASS(GPGSAppController)
So I was wondering if it's possible to subclass the Unity app controller from multiple places. I could not find any documentation for IMPL_APP_CONTROLLER_SUBCLASS
online.
Or maybe there is a better approach for adding custom initialization code in Unity on iOS?
I ended up swizzling UnityAppController
methods and doing initialization in my implementation of them.
Here is my solution in case anyone is interested:
#import <objc/runtime.h>
...
#import "UnityAppController.h"
namespace {
typedef BOOL (*ApplicationDidFinishLaunchingWithOptionsImp)(UnityAppController *appController,
SEL selector,
UIApplication *application,
NSDictionary *launchOptions);
ApplicationDidFinishLaunchingWithOptionsImp OriginalApplicationDidFinishLaunchingWithOptions;
BOOL ApplicationDidFinishLaunchingWithOptions(UnityAppController *appController,
SEL selector,
UIApplication *application,
NSDictionary *launchOptions) {
// Initialize Google Play Games, etc
return OriginalApplicationDidFinishLaunchingWithOptions(appController, selector, application, launchOptions);
}
IMP SwizzleMethod(SEL selector, Class klass, IMP newImp) {
Method method = class_getInstanceMethod(klass, selector);
if (method != nil) {
return class_replaceMethod(klass, selector, newImp, method_getTypeEncoding(method));
}
return nil;
}
} // anonymous namespace
@interface AppController : UnityAppController
@end
@implementation AppController
+ (void)load {
OriginalApplicationDidFinishLaunchingWithOptions = (ApplicationDidFinishLaunchingWithOptionsImp)
SwizzleMethod(@selector(application:didFinishLaunchingWithOptions:),
[UnityAppController class],
(IMP)&ApplicationDidFinishLaunchingWithOptions);
}
@end
Simply save this file as AppController.mm
and add it to your Assets folder. Unity will recognize it as an Objective-C++ source file and automatically include it in the generated Xcode project.
If you need to include frameworks or modify your Xcode project in other ways take a look at PostProcessBuildAttribute
and Xcode API
.