My company develops an advertising SDK that mediates other ad networks. At runtime, it loads constants from those SDKs using CFBundleGetDataPointerForName
, as outlined in this StackOverflow post.
However, I'm not able to get that approach to work to load the GADAdSize
constants that AdMob's banner SDK uses. Here's what my code looks like:
HZGADAdSize *hzlookupAdMobAdSizeConstant(NSString *const constantName) {
return CFBundleGetDataPointerForName(CFBundleGetMainBundle(), (__bridge CFStringRef)constantName);
}
HZGADAdSize *hzAdMobAdSizeFlexibleWidthPortrait(void) {
return hzlookupAdMobAdSizeConstant(@"kGADAdSizeBanner");
}
The above code works fine for loading similar constants, like Facebook's FBAdSize
struct, but the returned pointer is NULL
when trying to load any GADAdSize
constant.
Here's how the constant is defined in the AdMob SDK:
/// Do not create a GADAdSize manually. Use one of the kGADAdSize constants. Treat GADAdSize as an
/// opaque type. Do not access any fields directly. To obtain a concrete CGSize, use the function
/// CGSizeFromGADAdSize().
typedef struct GADAdSize {
CGSize size;
NSUInteger flags;
} GADAdSize;
#pragma mark Standard Sizes
/// iPhone and iPod Touch ad size. Typically 320x50.
extern GADAdSize const kGADAdSizeBanner;
Things I've tried so far
Trying with all bundles in the app:
CFArrayRef array = CFBundleGetAllBundles(); for (int i = 0; i < CFArrayGetCount(array); i++) { CFBundleRef bundle = (CFBundleRef)CFArrayGetValueAtIndex(array, i); void *ptr = CFBundleGetDataPointerForName(bundle, (__bridge CFStringRef)@"kGADAdSizeBanner"); if (ptr == NULL) { NSLog(@"pointer was NULL"); } else { NSLog(@"pointer was present!!"); } }
None of the bundles in the app have the constant, so I don't think its an issue of the pointers being in a different bundle.
Marking the constants as
extern
in my codeextern HZGADAdSize const kGADAdSizeSmartBannerPortrait;
The extern
approach lets me reference the constants, but if AdMob isn't present when the app is compiled, I get compiler errors about the missing constants, so I don't think this option is feasible since many of our developers won't use AdMob.
Loading function pointers from the same class. Edit: I was mistaken; I can't load function pointers either. I also can't load string constants.
void *ptr = CFBundleGetFunctionPointerForName(CFBundleGetMainBundle(), (__bridge CFStringRef)@"CGSizeFromGADAdSize"); // returns NULL
To avoid XY problems: Our SDK loads constants at runtime so that if e.g. the AdMob SDK is present, we can pass the constants it defines to it. If the SDK isn't present (e.g. when the developer isn't using AdMob but is using other ad networks), we still need our SDK to compile without AdMob being there. If there's a way we can accomplish this without loading values at runtime, that's just as good a solution for me.
Version Information:
- AdMob SDK 7.0.0
- iPhone 6 Simulator
- iOS 8.2
- Xcode 6.2