iOS 7如何实现UI元素,使其看起来不同,取决于您编译的SDK?
UITableView
, UINavigationBar
等元素在iOS 7上有不同的风格。
这种风格是在运行时确定的,因为这些类是在UIKit
上实现的,并且UIKit
在运行时dynamic链接到应用程序,而不是在编译时静态的。
所以人们会认为在iOS 7上运行的任何应用程序都会让这些元素看起来像他们在iOS 7上看起来的样子。但是,他们保持原来在iOS 6上的风格,直到您使用iOS 7 SDK进行编译。 除了其中一些(如UIAlertView
或UIMenuController
)
我唯一的解释是他们做了这样的事情:
#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链接。