可以在运行时确定用于以编程方式构建二进制文件的iOS SDK版本吗?

Mic*_*son 7 sdk xcode objective-c ios ios8

啊,iOS 8 - 从iOS 7到很多意想不到的变化!

tl; dr:有没有办法在运行时以编程方式确定用于构建应用程序的iOS SDK版本(不使用预处理器宏)?

我正在努力为我维护的库(分布为预构建的静态库)进行一些窗口框计算,因为iOS 8改变了屏幕坐标系的工作方式.

两个初步观察,运行iOS 7的代码,iOS 8没有变化:

  1. 使用iOS 7 SDK构建并在iOS 8上运行时,一切都可以像以前一样工作,无需进行任何更改.
  2. 当使用iOS 8 SDK构建并在iOS 8上运行时,它已被破坏:需要对帧计算进行一些更改才能获得正确的定位.

因此,我们在条件打开时更改代码,[[UIDevice currentDevice] systemVersion]以便与新坐标系统一起正常工作.现在:

  1. 使用iOS 7 SDK构建并在iOS 7上运行时,一切正常.
  2. 使用iOS 8 SDK构建并在iOS 8上运行时,一切正常.

    但:

  3. 当使用iOS 7 SDK构建并在iOS 8上运行时,计算结束 - 请记住,当使用iOS 7 SDK构建时,在iOS 8特定代码更改之前一切正常.所以,所做的改变实际上破坏了东西.

现在,通常情况下,我可以通过SDK版本(#ifdef __IPHONE_8_0等等)上的一些宏条件解决这个问题.但我正在分发一个使用iOS 7 SDK构建的预构建静态库,因此这些条件中的代码永远不会进入.这就是为什么这是一个问题:

如果静态库是使用iOS 7 SDK构建的,但是链接到使用iOS 8 SDK构建的应用程序,那就像使用iOS 8 SDK构建静态库一样(因为链接发生在最终的应用程序编译阶段) , 当然).这意味着我需要在那里进行iOS 8更改,当应用程序使用iOS 8 SDK构建时 - 但是我不能使用宏条件来确定是否使用它们,因为C预处理器在iOS 7下的静态库构建.

所以,我的问题是这样的:有没有人知道我是如何能够确定应用程序构建是在运行时从预编译的静态库中使用iOS 8 SDK进行的?

我确实尝试检查仅支持iOS 8的SDK功能(-[UIScreen nativeBounds]例如),但这不会飞 - 无论SDK版本如何,该符号都可用.

有人有主意吗?

Tom*_*mmy 5

经验性,无证件的观察如下:

苹果记录您对建在按键下的Info.plist的SDK DTSDKBuildDTSDKName,等等.其中DTSDKName似乎可以在运行时访问,并以SDK编号结束.所以,得到一个:

- (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;
Run Code Online (Sandbox Code Playgroud)

......有一个重要的警告,我只是逆向设计,经验上.因此,它是技术上未记录的API,并且无法保证未来的稳健性.

然后你可以使用:

BOOL wasBuiltForiOS8 = 
    [[self buildVersion] compare:@"8.0"] != NSOrderedAscending;
Run Code Online (Sandbox Code Playgroud)

(YES如果没有找到版本字符串,它有一个很好的功能,它会评估,所以从技术上来说,如果Apple DTSDKBuild将来拿走它并不重要,它只是不会追溯性地从7中删除它. x或某种方式有一天使用8.0之前按字母顺序排列的版本字符串