-
Star
(163)
You must be signed in to star a gist -
Fork
(7)
You must be signed in to fork a gist
-
-
Save steipete/6526860 to your computer and use it in GitHub Desktop.
| // Taken from http://PSPDFKit.com. This snippet is under public domain. | |
| #define UIKitVersionNumber_iOS_7_0 0xB57 | |
| BOOL PSPDFIsUIKitFlatMode(void) { | |
| static BOOL isUIKitFlatMode = NO; | |
| static dispatch_once_t onceToken; | |
| dispatch_once(&onceToken, ^{ | |
| // We get the modern UIKit if system is running >= iOS 7 and we were linked with >= SDK 7. | |
| if (kCFCoreFoundationVersionNumber >= kCFCoreFoundationVersionNumber_iOS_7_0) { | |
| isUIKitFlatMode = (NSVersionOfLinkTimeLibrary("UIKit") >> 16) >= UIKitVersionNumber_iOS_7_0; | |
| } | |
| }); | |
| return isUIKitFlatMode; | |
| } |
In order to check which SDK version was used to build a binary, UIKit uses the _UIApplicationLinkedOnOrAfter function. It is implemented by comparing the major version of UIKit at link time (NSVersionOfLinkTimeLibrary("UIKit") >> 16) to a value in the __UIKitVersionNumbers table.
Here is this UIKit version numbers table, built by running otool -L on UIKit of all these iOS versions (yes I have a huge archive!):
| Index | iOS Version | Hexadecimal | Decimal |
| 0 | 2.0 | 0x0E5 | 229 |
| 1 | 2.1 | 0x2EB | 747 |
| 2 | 2.2 | 0x2F0 | 752 |
| 3 | 2.2.1 | 0x2F1 | 753 |
| 4 | 3.0 | 0x333 | 819 |
| 5 | 3.1 | 0x3E8 | 1000 |
| 6 | 3.2 | 0x44C | 1100 |
| 7 | 4.0 | 0x4B0 | 1200 |
| 8 | 4.1 | 0x514 | 1300 |
| 9 | 4.2.1 | 0x578 | 1400 |
| 10 | 4.2.6 | 0x582 | 1410 |
| 11 | 4.3 | 0x5DC | 1500 |
| 12 | 5.0 | 0x640 | 1600 |
| 13 | 5.1 | 0x6A4 | 1700 |
| 14 | 6.0 | 0x944 | 2372 |
| 15 | 6.1 | 0x94C | 2380 |
| 16 | 7.0 | 0xB57 | 2903 |
| 17 | 7.1 | 0xB77 | 2935 |
Weirdly enough, the __UIKitVersionNumbers contains 0x2EC instead of 0x2EB for iPhone OS 2.1. But since nobody cares at all about iPhone OS 2 this should not be a problem.
Awesome thread!
One tiny thing to add:
If kCFCoreFoundationVersionNumber_iOS_7_0 is undefined, use following snippet:
ifndef kCFCoreFoundationVersionNumber_iOS_7_0
define kCFCoreFoundationVersionNumber_iOS_7_0 847.2
endif
Instead of the defining the var I would use the & ... like
if (&kCFCoreFoundationVersionNumber_iOS_7_0 &&
kCFCoreFoundationVersionNumber >= kCFCoreFoundationVersionNumber_iOS_7_0)
{ ...
For anyone googling their way here, 8.0 is 0xCF6.
iOS 9.3: 0xDB8
iOS 10b4: 0xE0C
For iOS 12 (GM), it seems that casting to unsigned integer is now required:
(lldb) p (int32_t)NSVersionOfLinkTimeLibrary("UIKit") >> 16
(int32_t) $4 = -4536
(lldb) p (uint32_t)NSVersionOfLinkTimeLibrary("UIKit") >> 16
(uint32_t) $5 = 61000
-> UIKitVersionNumber_iOS_12_0 = 0xEE48
iOS 15.0 is 0x13CB
(lldb) p (uint32_t)NSVersionOfLinkTimeLibrary("UIKit") >> 16
(uint32_t) $2 = 5067
iOS 15.2 is 0x1455
(lldb) p (uint32_t)NSVersionOfLinkTimeLibrary("UIKit") >> 16
(uint32_t) $1 = 5205
Check the
dyld(3)man page:They're just whatever number the team for that library uses.