iOS 7如何实现UI元素,使其看起来不同,取决于您编译的SDK?

UITableViewUINavigationBar等元素在iOS 7上有不同的风格。

这种风格是在运行时确定的,因为这些类是在UIKit上实现的,并且UIKit在运行时dynamic链接到应用程序,而不是在编译时静态的。

所以人们会认为在iOS 7上运行的任何应用程序都会让这些元素看起来像他们在iOS 7上看起来的样子。但是,他们保持原来在iOS 6上的风格,直到您使用iOS 7 SDK进行编译。 除了其中一些(如UIAlertViewUIMenuController

我唯一的解释是他们做了这样的事情:

 #define SDKApplicationWasLinkedAgainst ... if (SDKApplicationWasLinkedAgainst < 7.0) ... else ... 

这显然非常麻烦,因为他们需要保持大量的旧代码。 所以我很好奇,这真的是在幕后发生了什么? 我错过了什么?

不用过多地进入NDA的领域,我只想说,是的,他们是基于以下调用的结果来调整外观和行为:

 _UIApplicationUsesLegacyUI() 

这个函数反过来调用了GSApplicationUsesLegacyUI() ,我认为这个函数返回的是一个基于链接的UIKit版本的结果。

这意味着,是的,它们是为了传统而对UIKit的某些部分进行条件化。 不知道这是一件好事,但他们决定这样做。

我敢打赌,他们使用框架兼容性版本 。

每次编译应用程序时,您的应用程序都会与特定的框架链接,并且具有兼容版本和当前版本。 你可以看到这些数字,如果你运行otool -L YourApp.app/YourApp 。 例如,对于前段时间编译的应用程序,我获得了这个:

 /System/Library/Frameworks/Foundation.framework/Foundation (compatibility version 300.0.0, current version 751.58.0) /System/Library/Frameworks/UIKit.framework/UIKit (compatibility version 1.0.0, current version 1500.0.0) 

正如你所看到的,UIKit框架的完整path存储在Mach-O二进制文件中,还有一些版本(特别是我当时编译的版本)。

我猜想iOS 7将包含两个UIKit版本:iOS6标有相应版本的版本,说明兼容性从1.0.0开始,iOS7开始标记为兼容高于1500.0.0的版本(我不知道如果这是iOS 6.1.3的数字,但你明白了)。

当你的iOS6二进制文件被加载时,它的库依赖被dyld读取并parsing,因为你编译时说的是current version 1500.0.0 ,而iOS 7的库说compatibility version 1501.0.0 ,你将被链接到iOS的库6。

由于框架也是一个捆绑包,所有的资源都被完全包含,只有正确的版本才能使用,这就是不同的视觉元素在iOS 6 SDK或iOS 7 SDK上编译时看起来会有什么不同。

我可能是错的,但我只是希望他们不使用你提出的代码技术,因为这将是一个糟糕的代码库来维护。

我不能确定,但​​这是如何做的一个猜测。 因为他们知道你的应用程序链接的SDK版本,所以他们在iOS 7设备上版本化框架。 所以,在/.../iPhoneOS6.1.sdk/.../Frameworks/UIKit的文件系统上有一个层次结构。 然后,当它加载你的应用程序,他们可以设置库的searchpath指向你的应用程序链接到哪个SDK。

这就是Xcode如何做的。 在Xcode包里面的Developer目录里面是一个SDKs目录,而SDK目录又包含了所有不同的SDK链接。