类是在两者中实现的,其中一个将被使用。哪一个未定义

时间:2017-10-25 12:22:15

标签: ios xcode cocoapods

我对Cocoapods中包含的依赖项存在问题。

我有一个Framework项目(MyFramework目标),它也有App目标(MyFrameworkExampleApp)。当我尝试运行应用程序时,我得到一个充满错误的控制台:

  

类PodsDummy_AFNetworking在/private/var/containers/Bundle/Application/AD85D7EC-2652-4019-94FB-C799D0FBA69B/MyFrameworkExampleApp.app/Frameworks/MyFramework.framework/MyFramework(0x1019a0438)和/ var / containers /中实现Bundle / Application / AD85D7EC-2652-4019-94FB-C799D0FBA69B / MyFrameworkExampleApp.app / MyFrameworkExampleApp(0x10107c558)。将使用两者之一。哪一个未定义。

问题是,错误来自仅包含在MyFramework目标中的库

以下是我的podfile的内容:

# Specify platform.
platform :ios, '9.0'

# Let's ignore all warnings from all pods
inhibit_all_warnings!

target 'MyFramework’ do

    # ReactiveCocoa for easier binding between UI and data models.
    pod 'ReactiveCocoa', '< 3.0'

    # ReactiveViewModel for easier handling of active/inactive view models.
    pod 'ReactiveViewModel', '0.3'

    # An Objective-C extension with some nice helpers including @weakify/@strongify.
    pod 'libextobjc', '~> 0.4.1'

    # AFNetworking Security stuff
    pod 'AFNetworking/Security', '~> 2.5.4'

    # KZPropertyMapper to easily map JSON dicts to properties
    pod "KZPropertyMapper"

    # Simple wrapper for KeyChain
    pod 'UICKeyChainStore', '~> 2.0.6'

    # Animated gifs
    pod 'FLAnimatedImage', '~> 1.0'

    # Firebase push notifications
    pod 'Firebase/Core'
    pod 'Firebase/Messaging'

    # Easy image downloading with cache.
    pod 'SDWebImage', '~> 3.7.2'

    # Activity indicator for RBSlider
    pod 'DGActivityIndicatorView'

end

target 'MyFrameworkExampleApp' do

    # Progress indicator
    pod 'MBProgressHUD', '~> 1.0.0'

    # Color picker
    pod 'iOS-Color-Picker'

    # Hockey SDK
    pod 'HockeySDK', '~> 5.0.0'

end

如您所见,App目标不继承任何pod,也没有任何全局pod。可能是什么原因?

5 个答案:

答案 0 :(得分:18)

我不知道原因,但如果您打开应用程序的Pods- [AppName] .debug.xcconfig文件,cocoapods创建您将找到OTHER_LDFLAGS,您将看到它链接到您链接的相同框架框架。因此,如果删除-framework [Duplicated framework],警告将消失。

似乎是一个cocoapods错误

答案 1 :(得分:7)

我还发现了另一个人写的脚本,可以自动修复bug。它只是做了我上面回答的那个。 将其添加到您的Podfile:

post_install do |installer|
    sharedLibrary = installer.aggregate_targets.find { |aggregate_target| aggregate_target.name == 'Pods-[MY_FRAMEWORK_TARGET]' }
    installer.aggregate_targets.each do |aggregate_target|
        if aggregate_target.name == 'Pods-[MY_APP_TARGET]'
            aggregate_target.xcconfigs.each do |config_name, config_file|
                sharedLibraryPodTargets = sharedLibrary.pod_targets
                aggregate_target.pod_targets.select { |pod_target| sharedLibraryPodTargets.include?(pod_target) }.each do |pod_target|
                    pod_target.specs.each do |spec|
                        frameworkPaths = unless spec.attributes_hash['ios'].nil? then spec.attributes_hash['ios']['vendored_frameworks'] else spec.attributes_hash['vendored_frameworks'] end || Set.new
                        frameworkNames = Array(frameworkPaths).map(&:to_s).map do |filename|
                            extension = File.extname filename
                            File.basename filename, extension
                        end
                    end
                    frameworkNames.each do |name|
                        if name != '[DUPLICATED_FRAMEWORK_1]' && name != '[DUPLICATED_FRAMEWORK_2]'
                            raise("Script is trying to remove unwanted flags: #{name}. Check it out!")
                        end
                        puts "Removing #{name} from OTHER_LDFLAGS"
                        config_file.frameworks.delete(name)
                    end
                end
            end
            xcconfig_path = aggregate_target.xcconfig_path(config_name)
            config_file.save_as(xcconfig_path)
        end
    end
end

答案 2 :(得分:2)

https://github.com/CocoaPods/CocoaPods/issues/7126#issuecomment-399395611

post_install do |installer|
    applicationTargets = [
        'Pods-SampleApp',
    ]
    libraryTargets = [
        'Pods-SampleLib',
    ]

    embedded_targets = installer.aggregate_targets.select { |aggregate_target|
        libraryTargets.include? aggregate_target.name
    }
    embedded_pod_targets = embedded_targets.flat_map { |embedded_target| embedded_target.pod_targets }
    host_targets = installer.aggregate_targets.select { |aggregate_target|
        applicationTargets.include? aggregate_target.name
    }

    # We only want to remove pods from Application targets, not libraries
    host_targets.each do |host_target|
        host_target.xcconfigs.each do |config_name, config_file|
            host_target.pod_targets.each do |pod_target|
                if embedded_pod_targets.include? pod_target
                    pod_target.specs.each do |spec|
                        if spec.attributes_hash['ios'] != nil
                            frameworkPaths = spec.attributes_hash['ios']['vendored_frameworks']
                            else
                            frameworkPaths = spec.attributes_hash['vendored_frameworks']
                        end
                        if frameworkPaths != nil
                            frameworkNames = Array(frameworkPaths).map(&:to_s).map do |filename|
                                extension = File.extname filename
                                File.basename filename, extension
                            end
                            frameworkNames.each do |name|
                                puts "Removing #{name} from OTHER_LDFLAGS of target #{host_target.name}"
                                config_file.frameworks.delete(name)
                            end
                        end
                    end
                end
            end
            xcconfig_path = host_target.xcconfig_path(config_name)
            config_file.save_as(xcconfig_path)
        end
    end
end

答案 3 :(得分:1)

已更新: 我为解决方案写了一篇博客文章:https://medium.com/@GalvinLi/tinysolution-fix-cocoapods-duplicate-implement-warning-5a2e1a505ea8

还有一个演示项目: https://github.com/bestwnh/TinySolution


我从互联网上获得了解决方案的主意,但找不到一个解决方案,因此我自己进行了变通。也许代码有点长,但是可以用。希望它可以帮助某人。

auto_process_target(,,)是关键功能,只需对其进行更改以适合您的项目,一切都将正常工作。 (因为我将一个框架用于多个应用程序目标,所以我将应用程序目标参数设为一个数组。)

post_install do |installer|

  # you should change the sample auto_process_target method call to fit your project

  # sample for the question
  auto_process_target(['MyFrameworkExampleApp'], 'MyFramework', installer)
  # sample for the multi app use on same framework
  auto_process_target(['exampleiOSApp', 'exampleMacApp'], 'exampleFramework', installer)

end

# the below code no need to modify

def auto_process_target(app_target_names, embedded_target_name, installer)
  words = find_words_at_embedded_target('Pods-' + embedded_target_name,
                                        installer)
  handle_app_targets(app_target_names.map{ |str| 'Pods-' + str },
                     words,
                     installer)
end

def find_line_with_start(str, start)
  str.each_line do |line|
      if line.start_with?(start)
        return line
      end
  end
  return nil
end

def remove_words(str, words)
  new_str = str
  words.each do |word| 
    new_str = new_str.sub(word, '')
  end
  return new_str
end

def find_words_at_embedded_target(target_name, installer)
  target = installer.pods_project.targets.find { |target| target.name == target_name }
  target.build_configurations.each do |config|
    xcconfig_path = config.base_configuration_reference.real_path
    xcconfig = File.read(xcconfig_path)
    old_line = find_line_with_start(xcconfig, "OTHER_LDFLAGS")

    if old_line == nil 
      next
    end
    words = old_line.split(' ').select{ |str| str.start_with?("-l") }.map{ |str| ' ' + str }
    return words
  end
end

def handle_app_targets(names, words, installer)
  installer.pods_project.targets.each do |target|
    if names.index(target.name) == nil
      next
    end
    puts "Updating #{target.name} OTHER_LDFLAGS"
    target.build_configurations.each do |config|
      xcconfig_path = config.base_configuration_reference.real_path
      xcconfig = File.read(xcconfig_path)
      old_line = find_line_with_start(xcconfig, "OTHER_LDFLAGS")

      if old_line == nil 
        next
      end
      new_line = remove_words(old_line, words)

      new_xcconfig = xcconfig.sub(old_line, new_line)
      File.open(xcconfig_path, "w") { |file| file << new_xcconfig }
    end
  end
end

如果一切正常。 Update xxxx OTHER_LDFLAGSpod install时,您会看到pod update。然后警告消失了。

enter image description here

答案 4 :(得分:0)

我遇到了同样的问题,在我的案例中,只是定义“ use_frameworks!” 作为全局解决方案即可。

更改Podfile后,您应该

  1. 清洁项目
  2. 从xcode退出
  3. 删除派生数据
  4. 安装Pod

要在下面挖掘的类似Podfile,

workspace 'sample'
# Comment the next line if you don't want to use dynamic frameworks
use_frameworks!
platform :ios, '13.0'

def sample_pods
  pod 'Alamofire' , '~> 5.1.0'
  pod 'RxSwift'
  pod 'CodableAlamofire'
end

def sample_framework_pods
  pod 'Alamofire' , '~> 5.1.0'
  pod 'RxSwift'
  pod 'CodableAlamofire'
end

target 'sample' do
  # Pods for sample
    sample_pods
end

target 'sample_framework' do
  project 'sample_framework/sample_framework.xcodeproj'
  # Pods for sample_framework
  sample_framework_pods
end