当新的 API 出现时,构建一个向后兼容的 OS X 应用程序?
Posted
技术标签:
【中文标题】当新的 API 出现时,构建一个向后兼容的 OS X 应用程序?【英文标题】:Building a backwards compatible OS X app, when a new API is present? 【发布时间】:2009-09-10 17:35:12 【问题描述】:我正在尝试升级应用程序 (Clarke) 以提供 10.6 兼容性。
我的计划是根据使用的 OSX 版本使用两种不同的代码路径。
在 10.5 上,它将使用一个控制器,该控制器由完全自定义的代码组成,不依赖于任何特定的 Cocoa API。在 10.6 上,它将使用另一个控制器,它将新的 CoreLocation API 包装在一个相同的接口中,基于相同的抽象类。在运行时,应用将通过检测操作系统版本在控制器之间切换。
这在为 10.6 SDK 构建的 10.6 上运行良好,但相同的构建在 10.5 上会崩溃:
10/09/2009 18:30:50 [0x0-0x12f12f].uk.co.tomtaylor.Clarke[4575] dyld: unknown required load command 0x80000022
10/09/2009 18:30:51 com.apple.launchd[403] ([0x0-0x12f12f].uk.co.tomtaylor.Clarke[4575]) Exited abnormally: Trace/BPT trap
如果我为 10.5 SDK 构建,它显然无法编译 CoreLocation 的东西。
我希望能够为此应用程序提供一个二进制文件。有没有办法从 10.5 中“隐藏”CoreLocation API?
【问题讨论】:
【参考方案1】:仅当您在两个平台上具有相同的框架但在较新的平台上有新调用时,部署 SDK 技巧才有效。对于 CoreLocation,10.5 中缺少整个框架,因此您的应用将无法加载,因为它无法动态绑定到框架。
你需要做以上,加上CoreLocation作为一个弱框架。选择您的链接框架和二进制文件构建阶段,在详细视图中找到 CoreLocation,然后在中间列中将“必需”更改为“弱”。
当您构建应用时,Xcode 会将 -weak_framework CoreLocation 传递给链接器,并且无论是否存在 CoreLocation,您的应用都会在所有 10.5 和 10.6 系统上加载。不过,除非您实际上是在 10.6 上运行,否则您可以确保不调用任何 CoreLocation 方法。
【讨论】:
【参考方案2】:您应该能够通过更改目标的构建设置来解决此问题:
-
将基础 SDK 设置为 10.6
将部署 SDK 设置为 10.5
【讨论】:
这是正确的方法,但还有更多:当您需要调用 10.6 而不是 10.5 中的 API 时,您需要使用 NSClassFromString() 获取类名。然后检查返回的类名是否有效。如果有效,您可以继续调用所需的 API。如果没有,您需要优雅地进行故障转移。以上是关于当新的 API 出现时,构建一个向后兼容的 OS X 应用程序?的主要内容,如果未能解决你的问题,请参考以下文章
App Sandbox/iCloud 和 Snow Leopard 向后兼容