使用框架

时间:2017-02-08 13:11:55

标签: ios swift cocoapods

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

  • MyApp:主要目标
  • MyAppKit:构建应用程序及其扩展程序之间共享的代码框架的目标,主要是API后端和数据库处理
  • MyAppWidget:使用MyAppKit框架的今日视图窗口小部件(或现在称之为的任何内容)。

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

使用此配置,pod install运行良好,但在MyAppWidget目标的链接阶段编译失败:ld: framework not found Realm for architecture x86_64。这可以通过将“{1}}和Realm.framework明确添加到”带库的链接二进制文件“部分以及目标的RealmSwift.framework中的以下构建设置来修复:

Pods-MyAppWidget.[debug/release].xcconfig

但是,每当我运行FRAMEWORK_SEARCH_PATHS = $(inherited) "$PODS_CONFIGURATION_BUILD_DIR/Realm" "$PODS_CONFIGURATION_BUILD_DIR/RealmSwift"` 时,构建设置都会自动恢复,我必须再次添加构建设置。

我看到以下解决方案:

  • 每次添加pod install挂钩添加这些设置但看起来确实“hacky”,经过几次误导尝试后,我找不到API参考,也不知道如何将这些设置添加到{{ 1}}通过脚本进行目标。
  • 将Podfile更改为以下结构(甚至将其包装在抽象目标中):

    post_install

    对于我来说这似乎是合乎逻辑的“小部件应该知道在链接期间要查看的位置但不需要pod本身”但这不会添加上述构建设置(我可能会误解MyAppWidget继承)(编辑:它实际上有效,但没有抽象目标)。这个想法来找我,因为在旧版本的CocoaPods中,solution显然是要添加[...] 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 ,现在已弃用。

  • :search_paths目标中展示Realm,但是这与我在主代码中无法访问“后端”代码的目标相冲突(可能纯粹是审美的?)。

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

提前干杯谢谢!

修改

关注Prientus' comment我已经探索了抽象和继承的可能性。我现在发现的根本问题实际上是多方面的:

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

使用这最后一个选项并手动链接Realm.framework可以工作,但对于我的意图和以前的工作是不是最理想的。根据{{​​3}} various issues Cocoapods的GitHub,其中一些问题似乎是一个错误。我已添加on,并会在有新闻时更新。

3 个答案:

答案 0 :(得分:12)

那么,是什么给出了:

  • 我对“在目标之间分离吊舱”的担忧是荒谬的,因为你仍然可以将它们导入任何地方。
  • “你必须手动链接”问题由一个简单的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目标继承”。我确实学到了很多东西。干杯!

答案 1 :(得分:5)

我不认识你。但对我来说,扩展和主机应用程序包含框架定义的所有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文件。

答案 2 :(得分:1)

这是一个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