Is it possible to determine the version of the iOS SDK used to create the binary programmatically at runtime?

Ah, iOS 8 - a lot of unexpected changes from iOS 7 to account for!

tl; dr: is there a way to programmatically determine the version of the iOS SDK used to create the application at run time (not with a preprocessor macro)?

I am struggling with some window frame calculations for the library I support (distributed as a static static library), since iOS 8 has changed the way the screen coordinate system works.

Two initial observations, the launch code for iOS 7 is unchanged for iOS 8:

  • When building with the iOS 7 SDK and running on iOS 8, everything works as before, no changes are required.
  • When building with the iOS 8 SDK and running on iOS 8, it is broken: for proper positioning, some changes in the frame calculation are necessary.

So, we change the code with conditional expressions to [[UIDevice currentDevice] systemVersion] to work correctly with the new coordinate system. Now:

  • When building with the iOS 7 SDK and running on iOS 7, everything works.
  • When building with iOS 8 SDK and running on iOS 8, everything works.

    BUT:

  • When it is built using the iOS 7 SDK and runs on iOS 8, the calculations are inactive - remember that when building with the iOS 7 SDK everything worked fine before changing the code on iOS 8. Thus, the changes made actually broke the material.

Now, as a rule, I could happily solve this with some macros in the SDK version ( #ifdef __IPHONE_8_0 , etc.). But I am distributing a pre-built static library created using the iOS 7 SDK, so the code inside these conditional expressions would never become. This is why this problem:

If the static library is built using the iOS 7 SDK, but it is connected to the application created using the iOS 8 SDK, then it is the same as if the static library was built using the iOS 8 SDK (because the connection occurs in the final stage of the application compilation , sure). This means that I need to have these iOS 8 changes where the application is built using the iOS 8 SDK, but I cannot use the macro to determine whether to use them, since the C preprocessor did its job during the static library in iOS 7.

So my question is this: does anyone know how I can determine if there was an application build using the iOS 8 SDK at runtime from a precompiled static library?

I tried to test the SDK function only for iOS 8 (for example, -[UIScreen nativeBounds] ), but this does not fly - the symbol is available regardless of the version of the SDK.

Does anyone have any ideas?

+6
source share
2 answers

Empirical, undocumented observations follow:

Apple writes the SDK that you created in Info.plist under the keys DTSDKBuild and DTSDKName , among others. Of these, the DTSDKName seems to be available at run time and ends with the SDK number. So, having received:

 - (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 caution I just changed, I did it empirically. So this is a technically undocumented API, and there is no guarantee of reliability in the future.

Then you can simply use:

 BOOL wasBuiltForiOS8 = [[self buildVersion] compare:@"8.0"] != NSOrderedAscending; 

(which has a good function that it will evaluate to YES if the version string is not found, so it doesn’t technically matter if Apple will cancel DTSDKBuild in the future, it’s only important that they don’t retroactively remove it from 7.x or some other way use a version string that is in alphabetical order up to 8.0)

+5
source

Here the temporary solution is hacking; it would be nice to have something more reliable.

 - (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; } 
+3
source

Source: https://habr.com/ru/post/974451/


All Articles