处理iOS框架项目的依赖关系

18

我使用以下方法创建了iOS框架项目:https://github.com/jverkoey/iOS-Framework

这个方法非常好用,但是我有点困惑,不知道如何包含我的框架所需的库/框架,特别是如何做到第三方客户端应用程序在使用我的框架时也可以包含这些库而不会出现冲突。

假设我的框架代码需要以下两个东西:

  • FacebookSDK.framework
  • libFlurry.a

第一个是iOS框架。当我将它添加到我的框架的“链接二进制文件与库”阶段并尝试编译使用我的框架的客户端项目时,链接器会抱怨缺少符号-我需要将FacebookSDK添加到客户端项目中,这很好:如果客户端应用程序想要使用Facebook,就没有可能发生冲突。

然而,当我对Flurry静态库执行相同操作时,在编译客户端项目时会出现重复的符号错误,这让我感到困惑,因为FacebookSDK.framework难道不只是一个打包的静态库吗?

ukaszs-iMac:FacebookSDK.framework lukasz$ file Versions/A/FacebookSDK 
Versions/A/FacebookSDK: Mach-O universal binary with 3 architectures
Versions/A/FacebookSDK (for architecture i386): current ar archive random library
Versions/A/FacebookSDK (for architecture armv7):    current ar archive random library
Versions/A/FacebookSDK (for architecture cputype (12) cpusubtype (11)): current ar archive random library

所以我的问题是:

  1. 为什么嵌入在框架中的库(比如Facebook)没有链接到我的框架项目产品,而作为.a文件包含的库则有链接?
  2. 如何将.a文件包含在我的框架中,以便当客户端应用程序使用我的框架时也需要这个特定的静态库时,不会产生重复符号错误?
7个回答

17

针对您所描述的使用情况,您应该从应用程序中链接到这些外部库,而不是您自己的框架。可以选择一个或另一个,但不能两者兼备。

如果您决定这些依赖关系属于应用程序的责任,您将从“链接二进制文件和库”以及任何其他显式链接配置中删除它们,并仅使用指向这些框架和库的路径来构建您的框架项目,以便它可以在编译时找到符号(但不链接)。 (即库的路径应包括LIBRARY_SEARCH_PATHS)。


我想创建一个依赖Google Maps sdk的框架。您能告诉我具体步骤吗? - Invincible
11
如果框架使用#import "FacebookSDK.h",那么该框架的依赖关系将从应用程序中链接。如果要创建该框架自身的二进制文件,由于FacebookSDK的未定义符号,它将失败。你能解释一下吗? - hariszaman

4
  1. 使用CocoaPods,它很容易使用(http://cocoapods.org/)。

  2. 您的应用程序开发人员需要包括podfile并下载依赖项。

  3. 在开发SDK时,请在SDK之上使用参考应用程序/演示应用程序来模拟此过程。


快速提问,试图弄清楚当一个应用程序使用2个框架并且这两个框架都使用一个共享库时,构建应用程序时链接器是否会出现问题? - Bob
不,我认为不行,因为你只公开了一个 Pod 文件。 - rustylepord
2
不确定这个答案的实用性如何。它确实减轻了框架开发人员的痛苦。你不能强迫使用你的框架的用户使用Cocoapods,特别是当他们的应用程序正在使用其他依赖项管理系统或他们的应用程序已经存在一段时间并且他们只想为新添加部分包含你的框架时。 - nsuinteger
@rustylepord,你有关于这个的教程吗?我想开发一个使用FB SDK的框架,我想把我的框架给我的供应商,一旦他们使用cocoapods安装我的框架,它也应该作为依赖项安装FB。 - anoop4real

2
在构建框架时,不应链接任何内容,而应仅创建一个带有框架对象的 *.a 二进制文件。
此外,您不应在框架中包含其他库的代码,因为客户端应用程序可能直接添加相同的库或者需要不同版本的库,从而创建冲突。
当然,您可以引用其他库中的 *.h 头文件以编译您的对象。
因此,安装步骤应详细说明所需的其他框架/库、其支持的版本、如何添加资源文件(如果有)等。这些只是许多原因之一,您可能要考虑创建一个CocoaPodspodspec

1
你应该使用CocoaPods。Facebook的依赖可以通过链接到CocoaPod来完成。
如果你想在pod中包含特定版本的Facebook,可以将其放入你的repo,并使用“vendored_frameworks”属性引用它。
同样,如果你想使用“vendored_libraries”来供应libFlurry.a,也可以这样做。
对于系统库,你不需要提供它们,例如“libZ.a”。
我强烈建议使用“pod lib create YourPodName”创建你的CocoaPod。他们最近改变了这个机制,非常棒。
你可以创建一个示例项目,展示如何在应用程序上下文中使用你的代码。
然后,我刚刚学到的另一件很酷的事情之一,是有人可以使用“pod try YourPodName”,它将自动下载、集成和运行Xcode项目。
CocoaPods值得一试。

对于大型框架(例如Parse和Facebook)以及在使用多个自定义开发pod时,我发现CocoaPods会减慢您的开发速度,因为它需要重新编译SDK的所有源代码以及您的代码。 - fatuhoku
@fatuhoku 我最近一直在尝试解决我们公司自己开发的 pod 的这个问题。应该有一种方法可以利用 pod 规格说明文件,而不需要每次都重新编译所有内容。但我还没有想出来。 - funroll
@funroll 我需要在我的podfile中包含哪些代码才能链接到一个pod呢? - Fernando Reynoso

1
我正在使用CocoaPods构建我的框架项目。 该框架使用了一些来自CocoaPods的第三方库。 Podfile指定在框架目标上安装依赖项。 当我构建框架时,它会将所有库都包含在二进制文件中。
如果我在Podfile中添加use_frameworks!,则在构建框架时,它将不包括第三方库。

嗨Evan,我有同样的需求,并且正在使用你上面提到的动态框架相同的步骤进行编译和链接,结果符合预期。现在我需要生成一个包含第三方库的二进制文件的静态框架。我该怎么做?为了构建一个静态框架,我只需将Mach-O类型更新为静态库,就能够生成静态框架,但是二进制文件没有第三方库。 - Shiva Reddy

0

-3

大多数情况下,如果您安装第三方框架,可以使用CocoaPods进行安装(这非常好,我肯定会这样做),或者他们提供您下载该框架并将其包含在您的项目中。

如果您决定下载库并将其包含在其中,则通常在“入门指南”中列出了您需要的框架列表。

意思是:建议使用CocoaPods安装并下载您的库,但不要包含其他任何内容,请给他们一个所需框架的列表。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接