Ah, iOS 8 - lots of unexpected changes from iOS 7 to account for!
tl;dr: Is there a way to programmatically determine the iOS SDK version used to build an app, at run-time (not with a preprocessor macro)?
I'm struggling with some window frame calculations for a library I maintain (distributed as a pre-built static library), as iOS 8 has changed the way the screen coordinate system works.
Two initial observations, running code for iOS 7 with no changes for iOS 8:
So, we change the code, with conditionals on [[UIDevice currentDevice] systemVersion]
, to work correctly with the new coordinate system. Now:
When built with the iOS 8 SDK, and run on iOS 8, everything works.
BUT:
When built with the iOS 7 SDK, and run on iOS 8, the calculations are off - remember, when built with the iOS 7 SDK, everything worked fine prior to the iOS 8-specific code changes. So, the changes made actually broke stuff.
Now, normally, I could happily solve this with some macro conditionals on the SDK version (#ifdef __IPHONE_8_0
, etc). But I'm distributing a pre-built static library, built with the iOS 7 SDK, so the code within those conditionals would never make it in. Here's why that's a problem:
If the static library is built with the iOS 7 SDK, but linked into an app built with the iOS 8 SDK, it's the same as if the static library were built with the iOS 8 SDK (because the linking happens at the final app compilation stage, of course). That means I need to have those iOS 8 changes in there, when the app is built with the iOS 8 SDK -- but I can't use a macro conditional to determine whether to use them, as the C preprocessor did its thing during the static library build under iOS 7.
So, my question is this: does anyone know how I might be able to determine whether the app build was made with the iOS 8 SDK, at runtime, from within the pre-compiled static library?
I did try checking for an iOS 8-only SDK feature (-[UIScreen nativeBounds]
, for example), but that doesn't fly -- the symbol's available regardless of SDK version.
Anyone have any ideas?
The iOS SDK (iOS Software Development Kit), formerly the iPhone SDK, is a software development kit (SDK) developed by Apple Inc. The kit allows for the development of mobile apps on Apple's iOS and iPadOS operating systems.
The iOS & iPadOS 14 SDK provides support to develop apps for iPhone, iPad, and iPod touch devices running iOS & iPadOS 14. The SDK comes bundled with Xcode 12, available from the Mac App Store.
SWIFT Software Development Kit (SDK) provides a simplified way for developers to consume the growing number of API-based services available on the SWIFT platform. The SDK delivers APIs that hide much of lower-level application plumbing, including authentication, authorization, signing and error handling.
Empirical, undocumented observations follow:
Apple records the SDK you built against in the Info.plist under the keys DTSDKBuild
and DTSDKName
, amongst others. Of those DTSDKName
seems to be accessible at runtime and ends with the SDK number. So, getting a:
- (NSString *)buildVersion
{
// form character set of digits and punctuation
NSMutableCharacterSet *characterSet =
[[NSCharacterSet decimalDigitCharacterSet] mutableCopy];
[characterSet formUnionWithCharacterSet:
[NSCharacterSet punctuationCharacterSet]];
// get only those things in characterSet from the SDK name
NSString *SDKName = [[NSBundle mainBundle] infoDictionary][@"DTSDKName"];
NSArray *components =
[[SDKName componentsSeparatedByCharactersInSet:
[characterSet invertedSet]]
filteredArrayUsingPredicate:
[NSPredicate predicateWithFormat:@"length != 0"]];
if([components count]) return components[0];
return nil;
}
BOOL wasBuiltWithiOS8SDK =
[[[NSBundle mainBundle] infoDictionary][@"DTSDKBuild"] compare:@"11D167"]
== NSOrderedDescending;
... with the heavy caveat that I've just reverse engineered that, empirically. So it's technically undocumented API and there's no guarantee whatsoever of robustness in the future.
You could then just use:
BOOL wasBuiltForiOS8 =
[[self buildVersion] compare:@"8.0"] != NSOrderedAscending;
(which has the nice feature that it'll evaluate to YES
if the version string isn't found, so technically it doesn't matter if Apple takes away DTSDKBuild
in the future, it only matters that they don't retroactively remove it from 7.x or somehow one day use a version string that is alphabetically before 8.0)
Here's a provisional solution - hacky, though; it'd be nice to have something more robust.
- (BOOL)hasiOS8ScreenCoordinateBehaviour {
if ( [[[UIDevice currentDevice] systemVersion] floatValue] < 8.0 ) return NO;
CGSize screenSize = [[UIScreen mainScreen] bounds].size;
if ( UIInterfaceOrientationIsLandscape([[UIApplication sharedApplication] statusBarOrientation]) &&
screenSize.width < screenSize.height ) {
return NO;
}
return YES;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With