使用框架在app扩展中使用Cocoapods

我有一个用Swift编写的应用程序(我们称之为MyApp),其中包含以下目标:

  • MyApp :主要目标
  • MyAppKit :构建应用程序及其扩展之间共享的代码框架的目标,主要是API后端和数据库处理
  • MyAppWidget :一个使用MyAppKit框架的Today View Widget(或者现在叫做的任何东西)。

MyAppKit框架链接到使用它的每个目标,即MyAppMyAppWidget 。 输入Cocoapods:我曾经拥有以下Podfile结构:

 platform :ios, '8.0' use_frameworks! target 'MyApp' do # Mostly UI or convenience pods pod 'Eureka', '~> 2.0.0-beta' pod 'PKHUD', '~> 4.0' pod '1PasswordExtension', '~> 1.8' end target 'MyAppKit' do # Backend pods for networking, storage, etc. pod 'Alamofire', '~> 4.0' pod 'Fuzi', '~> 1.0' pod 'KeychainAccess', '~> 3.0' pod 'RealmSwift', '~> 2.0' pod 'Result', '~> 3.0' end target 'MyAppWidget' do # Added here event though the target only imports MyAppKit but it worked pod 'RealmSwift', '~> 2.0' end 

这里的目的是仅将MyAppKit框架暴露给其他部分,而不是所有的pod(例如,我不希望能够在主应用程序中import Alamofire )。 但是,从Cocoapods 1.2.0 RC开始, pod install失败并出现以下错误: [!] The 'Pods-MyApp' target has frameworks with conflicting names: realm and realmswift. 。 它曾经工作,因为pods是为扩展名声明的,但只嵌入在主机应用程序中(有关详细信息,请参阅此问题 )。 所以我从小部件的目标中移除了pod,只留下了一个空白target 'MyAppWidget'行。

使用此配置, pod install运行正常,但在MyAppWidget目标的链接阶段编译失败: ld: framework not found Realm for architecture x86_64 。 这可以通过显式地将Realm.frameworkRealmSwift.framework添加到“Link Binary With Libraries”部分以及目标的Pods-MyAppWidget.[debug/release].xcconfig的以下构建设置来Pods-MyAppWidget.[debug/release].xcconfig

 FRAMEWORK_SEARCH_PATHS = $(inherited) "$PODS_CONFIGURATION_BUILD_DIR/Realm" "$PODS_CONFIGURATION_BUILD_DIR/RealmSwift"` 

但是,每当我运行pod install ,构建设置自然会被还原,我必须再次添加构建设置。

我看到以下解决方案:

  • 添加一个post_install挂钩,每次添加这些设置,但它看起来“hacky”,经过一些错误的尝试,我没有找到API参考,也不知道如何通过脚本将这些设置添加到MyAppWidget目标。
  • 将Podfile更改为以下结构(甚至将其包装在抽象目标中):

     [...] target 'MyAppKit' do # Backend pods for networking, storage, etc. pod 'Alamofire', '~> 4.0' pod 'Fuzi', '~> 1.0' pod 'KeychainAccess', '~> 3.0' pod 'RealmSwift', '~> 2.0' pod 'Result', '~> 3.0' target 'MyAppWidget' do inherit! :search_paths # Because else we get the "conflicting names" error end end 

    对于我而言,“小部件应该知道在链接期间要查看的位置,但不需要pod本身” ,这似乎是合乎逻辑的, 但这并没有添加上述构建设置(我可能误解了:search_pathsinheritance) (编辑:它实际上有效,但不是抽象目标)。 这个想法来找我,因为在旧版本的CocoaPods中, 解决方案显然是添加了link_with ,现在已经弃用了。

  • Expose Realm也在MyApp目标中,但是这与我在主代码中无法访问“后端”代码的目标相冲突(它可能纯粹是美观的?)。

所以,这是我的问题:什么是在主应用程序和扩展程序之间共享的框架中集成pod的最佳方式,同时仍然能够编译,而无需调整并手动添加内容?

欢呼并提前谢谢!


编辑

按照Prientus的评论,我探讨了抽象和inheritance的可能性。 我现在发现的潜在问题实际上是多方面的:

  • 它曾经在Cocoapods 1.2.0之前工作,因为在窗口小部件目标下声明的窗格嵌入在主机应用程序中但仍链接到窗口小部件。 不,它只是拒绝在“主要与扩展”关系中为不同的目标设置具有相同名称的pod
  • 使用抽象目标是不够的,因为目标不能仅从遗留目标inheritance搜索路径( inherit! :search_paths )。
  • 搜索路径可以从像MyAppKit这样的真实目标inheritance,但是这MyAppKit所有这些pod暴露给MyApp的代码(我想避免),并且仍然存在链接Realm框架的问题(因为实际上小部件使用最小的有点吸气,因此需要它)。

使用这最后一个选项并手动链接Realm.framework可以工作,但对于我的意图和以前的工作是不是最理想的。 根据Cocoapods的GitHub上的各种 问题 ,其中一些问题似乎是一个错误。 我添加了自己的问题,并在有新闻时更新。

那么,是什么给出了:

  • 我对“在目标之间分离豆荚”的关注是荒谬的,因为你仍然可以将它们导入任何地方。
  • “你必须手动链接”问题由一个简单的import RealmSwift语句import RealmSwift

因此,固定和工作的Podfile是:

 platform :ios, '8.0' use_frameworks! target 'MyApp' do pod 'Eureka', '~> 2.0.0-beta' pod 'PKHUD', '~> 4.0' pod '1PasswordExtension', '~> 1.8' end target 'MyAppKit' do pod 'Fuzi', '~> 1.0' pod 'RealmSwift', '~> 2.0' pod 'Alamofire', '~> 4.0' pod 'KeychainAccess', '~> 3.0' pod 'Result', '~> 3.0' target 'MyAppWidget' do inherit! :search_paths end end 

就是这样。 我会说旧的行为更明显,并且不需要阅读“podfile目标inheritance”。 我确实学到了很多东西。 干杯!

我不认识你。 但对我来说,扩展和主机应用程序包含框架定义的所有pod是完全合法和合理的。 这就是我的意思:

 def shared_pods pod 'Alamofire' end target 'Framework' do shared_pods end target 'Host' do shared_pods // Some other pods end target 'Extension' do shared_pods end 

我知道你很担心,但如果你考虑一下,你使用的所有第三方框架都会有依赖关系。 您不必担心它们,因为Cocoapods会为您照顾它们。 如果要使用它,则需要在列表中放置本地pod条目。

 target 'Host' do pod Framework, :path => '../Framework' end 

但是你必须维护podspec文件。

这是一个swift-3.0项目的配置文件示例。

 platform :ios, '8.0' def import_public_pods pod 'SwiftyJSON' end target 'Demo' do use_frameworks! # Pods for Demo import_public_pods pod 'Fabric' pod 'Crashlytics' target 'DemoTests' do inherit! :search_paths # Pods for testing end target 'DemoUITests' do inherit! :search_paths # Pods for testing end end target 'DemoKit' do use_frameworks! # Pods for DemoKit import_public_pods pod 'RealmSwift' target 'DemoKitTests' do inherit! :search_paths # Pods for testing end end