Fb80d6e17ae2151c4e4f56bfba3e4b3a
CocoaPods 历险 - Resolver 仲裁入口解析

CocoaPods 历险 - Resolver 仲裁入口解析

回顾

CocoaPods 历险 - 总览 中已经分析了 CocoaPods 的整个组件构成和职责。这篇博客单说在 Install 过程中的版本仲裁算法,其中包含了 Resolver 的入口过程以及 Molinillo 仲裁算法,这一篇我们来关注入口方案。

本文以 1.6.1 版本作为分析。后面从之前文章 CocoaPods 历险 - 总览 说到的 resolve_dependencies 依赖解析流程流程说起。

def resolve_dependencies
  # 拿到 plugin sources
  plugin_sources = run_source_provider_hooks
  # 创建一个 Analyzer
  # Analyzer 是通过分析, Podfile.lock, plugin_sources 返回一个 AnalysisResult
  # AnalysisResult 包括了 CocoaPods 依赖环境、CocoaPods 处理后在 xcodeproj 中的部分信息等。
  analyzer = create_analyzer(plugin_sources)

  # 如果标记了 repo_update (在 pod update 或者 pod install --repo-update 时生效)
  UI.section 'Updating local specs repositories' do
    # 更新 $HOME 目录下 CocoaPods 的本地 Specs 仓库
    analyzer.update_repositories
  end if repo_update?

  UI.section 'Analyzing dependencies' do
    # 调用 Analyzer 等 analyze 方法入口,并把部分结果拿回 install 类中
    analyze(analyzer)
    # 拼写错误降级识别,白名单过滤
    validate_build_configurations
    # 清理 sandbox 目录
    clean_sandbox
  end

  UI.section 'Verifying no changes' do
    verify_no_podfile_changes!
    verify_no_lockfile_changes!
  end if deployment?

  analyzer
end

在第一次构建依赖图的时候,由于 Molinillo 需要拿到所有的依赖信息,所以要在 Analyzer 分析出所有依赖节点才可以构建初始状态的依赖图。

Resolver 的依赖仲裁

Ruby 的项目中,往往最头疼的就是梳理各种各样的 ClassModule,在看 Molinillo 这个组件之前,笔者先整体浏览了一下这个库的代码结构。在 CocoaPods 项目中的算法入口其实是在 /lib/cocoapods/resolver.rb 这个文件中。你从它第一行的 require 'molinillo' 就可以意识到这个问题😂。

所以我在其 initialize 方法处,打印了运行堆栈,并且 raise 掉整个流程来调试 pod install 的过程,其 Log 如下:

lib/cocoapods/installer/analyzer.rb:908:in `new'
lib/cocoapods/installer/analyzer.rb:908:in `block in resolve_dependencies'
lib/cocoapods/user_interface.rb:64:in `section'
lib/cocoapods/installer/analyzer.rb:907:in `resolve_dependencies'
lib/cocoapods/installer/analyzer.rb:114:in `analyze'
lib/cocoapods/installer.rb:266:in `analyze'
lib/cocoapods/installer.rb:174:in `block in resolve_dependencies'
lib/cocoapods/user_interface.rb:64:in `section'
lib/cocoapods/installer.rb:173:in `resolve_dependencies'

我们从 resolve_dependencies 方法进入后,在实例化 Analyze 之后,其对象的 analyze 方法会在文件的 907 行(这个不是绝对的)调用 resolve_dependencies 从而触发了实例化 Resolver 对象的构造方法。

下面来看 analyze 是为什么要实例化 Resolver 对象。

def analyze(allow_fetches = true)
  # 如果已经有分析结果,直接返回
  return @result if @result
  # 校验 Podfile
  validate_podfile!
  # 校验 Podfile.lock 文件中 CocoaPods 的版本
  validate_lockfile_version!
  if installation_options.integrate_targets?
    # 预处理 Podfile 中每个 target 信息
    target_inspections = inspect_targets_to_integrate
  else
    # 校验声明的 platform 信息
    verify_platforms_specified!
    target_inspections = {}
  end
  # 调用 generate_podfile_state 来记录 sandbox 内每一个 Pod 的变化
  podfile_state = generate_podfile_state

  # 这里要存储非 Source Spec 下的 Options
  # 即 Podfile.lock 中的 CHECKOUT OPTIONS 字段
  # 通过 KV 方式进行预存,Key 为 Pod 的 Root Name
  store_existing_checkout_options
  if allow_fetches == :outdated
    # special-cased -- we're only really resolving for outdated, rather than doing a full analysis
    # 特殊边界情况,如果 outdated 则不参与全依赖分析
  elsif allow_fetches == true
    # 被告知需要 fetch,则说明我们需要 fetch 到远程仓库到 spec 文件
    fetch_external_sources(podfile_state)
  elsif !dependencies_to_fetch(podfile_state).all?(&:local?)
    # 需要检查如果需要更新到 spec 本地已经有对应版本,则通过
    # 否则跑出异常,告知 sandbox 不是最新版本
    raise Informative, 'Cannot analyze without fetching dependencies since the sandbox is not up-to-date. Run `pod install` to ensure all dependencies have been fetched.' \
      "\n    The missing dependencies are:\n    \t#{dependencies_to_fetch(podfile_state).reject(&:local?).join("\n    \t")}"
  end

  # 要点一:取出 Podfile.lock 中所有的依赖
  # 这个方法会返回一个初始化的依赖图,带有 Podfile.lock 中已经 lock 的所有依赖构成的多 root 图
  locked_dependencies = generate_version_locking_dependencies(podfile_state)
  # locked_dependencies.each do |item|
  #   puts item.name
  #   puts item.payload
  #   puts item.root
  # end
  # 要点二:根据 Target 对 Podfile 中的描述来对 spec 进行分组
  resolver_specs_by_target = resolve_dependencies(locked_dependencies)
  # 校验 platform 合法性
  validate_platforms(resolver_specs_by_target)
  # Spec 对实例数组
  specifications  = generate_specifications(resolver_specs_by_target)
  # 原工程中对 Targets 实例数组
  targets         = generate_targets(resolver_specs_by_target, target_inspections)
  # Pod Project 的 Targets 实例数组
  pod_targets     = calculate_pod_targets(targets)
  # Sandbox 中 Spec 数组,可理解成与 Manifest 状态同步
  sandbox_state   = generate_sandbox_state(specifications)
  # 根据 target 对 Spec 做分组操作
  specs_by_target = resolver_specs_by_target.each_with_object({}) do |rspecs_by_target, hash|
    hash[rspecs_by_target[0]] = rspecs_by_target[1].map(&:spec)
  end
  # 根据 sources 对 Spec 做分组操作
  specs_by_source = Hash[resolver_specs_by_target.values.flatten(1).group_by(&:source).map do |source, specs|
    [source, specs.map(&:spec).uniq]
  end]
  sources.each { |s| specs_by_source[s] ||= [] }
  # 要点三:返回一个 AnalysisResult 实例,得到最终的仲裁结果
  @result = AnalysisResult.new(podfile_state, specs_by_target, specs_by_source, specifications, sandbox_state,
                               targets, pod_targets, @podfile_dependency_cache)
end

要点一:SpecsState 溯源

analysis 方法是进入 Molinillo 的入口,generate_version_locking_dependencies 方法是用来生成 Podfile.lockPods 字段。追本溯源,可以先看下 generate_podfile_state 这个方法:

def generate_podfile_state
  if lockfile
    pods_state = nil
    UI.section 'Finding Podfile changes' do
      # diff podfile 解析结果
      pods_by_state = lockfile.detect_changes_with_podfile(podfile)
      # 通过 diff 结果生成 SpecsState 实例
      pods_state = SpecsState.new(pods_by_state)
      # verbose 下输出 log
      pods_state.print if config.verbose?
    end
    pods_state
  else
    state = SpecsState.new
    # 如果没有 lock 文件取出
    state.added.merge(podfile_dependencies.map(&:root_name))
    state
  end
end

源码层面上来看,在获取 SpecsState 的初始状态,会参考 PodfilePodfile.lock 文件中记录的信息。一次的 Analysis 过程会维护一个 SpecsState 对象,这个对象记录了多个状态数组,里面记录了不改四个状态。

class SpecsState
  # @return [Set<String>] 需要进行增操作的 Pod Name 集合
  #
  attr_reader :added

  # @return [Set<String>] 需要进行改操作的 Pod Name 集合
  #
  attr_reader :changed

  # @return [Set<String>] 需要进行删操作的 Pod Name 集合
  #
  attr_reader :deleted

  # @return [Set<String>] 无需修改的 Pod Name 集合
  #
  attr_reader :unchanged
end

在二次 pod install 的时候输出初始化比对后返回的 SpecsState 中的数据:

增加 #<Set: {}>
删除 #<Set: {}>
不改 #<Set: {"AcknowList", "ActiveLabel", "Alamofire", "AlamofireObjectMapper", "CocoaLumberjack", "CollectionKit", "Crashlytics", "Curiouscat", "DeviceKit", "DTCoreText", "DWAnimatedLabel", "EFQRCode", "Fabric", "FaveButton", "Firebase", "FLEX", "FTPopOverMenu_Swift", "GDMDebugger", "Highlightr", "KVOController", "lottie-ios", "LTMorphingLabel", "MJRefresh", "MMMarkdown", "NVActivityIndicatorView", "ObjectMapper", "pop", "PySwiftyRegex", "ReachabilitySwift", "SDWebImage", "SGQRCode", "SkeletonView", "SnapKit", "Straycat", "SwiftMessages", "SwiftyUserDefaults", "SwipeCellKit", "ViewAnimator", "WCDB.swift", "WCLShineButton", "WechatOpenSDK", "XLPagerTabStrip"}>
修改 #<Set: {}>

发现 Podfile 中声明的 Pod 依赖全部进入了 unchanged 集合,符合我们的预期。在这之后,将 SpecsState 传入 generate_version_locking_dependencies 中来继续处理。当然这一切都依托于我们当前目录下有 Podfile.lock 文件

def generate_version_locking_dependencies(podfile_state)
  if update_mode == :all || !lockfile
    LockingDependencyAnalyzer.unlocked_dependency_graph
  else
    # 从 state 中获取出 deleted 和 changed 的 Pod
    deleted_and_changed = podfile_state.changed + podfile_state.deleted
    # 已经更新的所有 Pods 或者是应该更新的 Pods 加入数组,在非 lock 状态下
    deleted_and_changed += pods_to_update[:pods] if update_mode == :selected
    # 获取出所有 path 指向的 Pod 名,这里只关心 root_name
    local_pod_names = podfile_dependencies.select(&:local?).map(&:root_name)
    # local pods 不进行 lock
    pods_to_unlock = local_pod_names.to_set.delete_if do |pod_name|
      next unless sandbox_specification = sandbox.specification(pod_name)
      sandbox_specification.checksum == lockfile.checksum(pod_name)
    end
    # 根据 lock 文件以及相关信息生成依赖图,并返回
    LockingDependencyAnalyzer.generate_version_locking_dependencies(lockfile, deleted_and_changed, pods_to_unlock)
  end
end

有 Podfile.lock 条件 - 生成版本 Locking 图

LockingDependencyAnalyzer 这个类用来生成未修改的 Pod 依赖项,这些依赖是存在于 Podfile.lock 中且标记成非更新状态的。如果是在非更新模式,pods_by_state 通过 LockingDependencyAnalyzer 初始化一个结果传递给 Resolver固化这些 Pod 版本。

# 自己添加的查询图节点的 log 方法
def self.check_dependency_graph(graph)
  puts "check dependency graph"
  res = []
  graph.each do |vertex|
    res << "#{vertex.payload}"
  end
  print res
  puts ""
end

# module Pod => class Installer => class Analysis => module LockingDependencyAnalyzer

def self.generate_version_locking_dependencies(lockfile, pods_to_update, pods_to_unlock = [])
  # lockfile - lock 文件
  # pods_to_update - 标记需要更新的 Pod 集合
  # pods_to_unlock - 不需 lock 的 Pod 集合
  puts("lockfile => ", lockfile.pod_names)
  puts("pods_to_update => ", pods_to_update)
  puts("pods_to_unlock => ", pods_to_unlock)

  dependency_graph = Molinillo::DependencyGraph.new

  if lockfile
    added_dependency_strings = Set.new

    # 拿出所有的显式依赖
    explicit_dependencies = lockfile.dependencies
    explicit_dependencies.each do |dependency|
      check_dependency_graph(dependency_graph)

      # 对依赖图进行加顶点,并且确定为 root 节点
      dependency_graph.add_vertex(dependency.name, dependency, true)
    end

    # 取出 lockfile 中 PODS 字段内容
    # 这个字段包含了上次记录的所有依赖
    pods = lockfile.to_hash['PODS'] || []
    # 遍历所有 Pods 进行增加 root 点操作
    pods.each do |pod|
      check_dependency_graph(dependency_graph)
      # 继续在图中加点,由于取的是 PODS 字段,所有依赖全部加入
      add_to_dependency_graph(pod, [], dependency_graph, pods_to_unlock, added_dependency_strings)
    end

    # 将 update 数组中的依赖通过 root name 进行转换
    pods_to_update = pods_to_update.flat_map do |u|
      root_name = Specification.root_name(u).downcase
      dependency_graph.vertices.each_key.select { |n| Specification.root_name(n).downcase == root_name }
    end

    # 将待更新节点做拆点操作
    pods_to_update.each do |u|
      dependency_graph.detach_vertex_named(u)
    end

    # 遍历图所有节点,增加 spec 仓的 git 地址
    dependency_graph.each do |vertex|
      next unless dep = vertex.payload
      dep.podspec_repo ||= lockfile.spec_repo(dep.root_name)
    end
  end

  dependency_graph
end

def self.add_child_vertex_to_graph(dependency_string, parents, dependency_graph, pods_to_unlock, added_dependency_strings)
  # 这里的去重用了 Set 的特性,如果是重复的元素,在 Set.add? 之后会返回 null
  # 所以这里如果是重复的节点,就直接 return
  return unless added_dependency_strings.add?(dependency_string)
  # 通过描述字符串获取出 Dependency 实例
  dependency = Dependency.from_string(dependency_string)
  # 如果在 pods_to_unlock 这个未加锁数组中,则只使用 Pods 名来实例化 Dependency
  if pods_to_unlock.include?(dependency.root_name)
    dependency = Dependency.new(dependency.name)
  end
  # 加边操作
  vertex = dependency_graph.add_child_vertex(dependency.name, nil, parents, nil)
  # 如果有 payload 信息,则合并版本约束
  dependency = vertex.payload.merge(dependency) if vertex.payload
  puts "合并版本约束 payload ", dependency
  # 修改节点的 payload 信息
  vertex.payload = dependency
  dependency
end

def self.add_to_dependency_graph(object, parents, dependency_graph, pods_to_unlock, added_dependency_strings)
  # 如果是 String 类型,代表是单一依赖,只有一个节点
  # Hash 会带上一组依赖关系
  case object
  when String
    add_child_vertex_to_graph(object, parents, dependency_graph, pods_to_unlock, added_dependency_strings)
  when Hash
    object.each do |key, value|
      dependency = add_child_vertex_to_graph(key, parents, dependency_graph, pods_to_unlock, added_dependency_strings)
      # 由于 PODS 信息中只有二级依赖关系,所有只遍历一层隐式依赖即可
      value.each { |v| add_to_dependency_graph(v, [dependency.name], dependency_graph, pods_to_unlock, added_dependency_strings) }
    end
  end
end

在我们拥有 Podfile.lock 的情况下,构建这个初始图就是比较容易的事情。重新梳理一下这个流程。首先我们解析完 Podfile.lockPodfile 之后,构造了一个 SpecsState 实例,这里面会分析出增、删、改、未改这四个 Pod 数组。由于已经存在 Podfile.lock 文件,将其中的 Dependency 字段,也就是 Podfile 里的显示依赖拿出来构造多个 root 节点。在以下 Log 中,我用(依赖比较少的)新项目来做测试:

check dependency graph
[]
加点 Alamofire Alamofire (~> 4.7.3) 根节点
check dependency graph
["Alamofire (~> 4.7.3)"]
加点 AlamofireObjectMapper AlamofireObjectMapper (~> 5.0) 根节点
check dependency graph
["Alamofire (~> 4.7.3)", "AlamofireObjectMapper (~> 5.0)"]
加点 CocoaLumberjack/Swift CocoaLumberjack/Swift 根节点
check dependency graph
["Alamofire (~> 4.7.3)", "AlamofireObjectMapper (~> 5.0)", "CocoaLumberjack/Swift"]
加点 DeviceKit DeviceKit (~> 2.0) 根节点
check dependency graph
["Alamofire (~> 4.7.3)", "AlamofireObjectMapper (~> 5.0)", "CocoaLumberjack/Swift", "DeviceKit (~> 2.0)"]
加点 ESTabBarController-swift ESTabBarController-swift 根节点
check dependency graph
["Alamofire (~> 4.7.3)", "AlamofireObjectMapper (~> 5.0)", "CocoaLumberjack/Swift", "DeviceKit (~> 2.0)", "ESTabBarController-swift"]
加点 FLEX FLEX (~> 2.0) 根节点
check dependency graph
["Alamofire (~> 4.7.3)", "AlamofireObjectMapper (~> 5.0)", "CocoaLumberjack/Swift", "DeviceKit (~> 2.0)", "ESTabBarController-swift", "FLEX (~> 2.0)"]
加点 IQKeyboardManagerSwift IQKeyboardManagerSwift (~> 6.2.0) 根节点
check dependency graph
["Alamofire (~> 4.7.3)", "AlamofireObjectMapper (~> 5.0)", "CocoaLumberjack/Swift", "DeviceKit (~> 2.0)", "ESTabBarController-swift", "FLEX (~> 2.0)", "IQKeyboardManagerSwift (~> 6.2.0)"]
加点 KVOController KVOController 根节点
check dependency graph
["Alamofire (~> 4.7.3)", "AlamofireObjectMapper (~> 5.0)", "CocoaLumberjack/Swift", "DeviceKit (~> 2.0)", "ESTabBarController-swift", "FLEX (~> 2.0)", "IQKeyboardManagerSwift (~> 6.2.0)", "KVOController"]
加点 ObjectMapper ObjectMapper (~> 3.1) 根节点
check dependency graph
["Alamofire (~> 4.7.3)", "AlamofireObjectMapper (~> 5.0)", "CocoaLumberjack/Swift", "DeviceKit (~> 2.0)", "ESTabBarController-swift", "FLEX (~> 2.0)", "IQKeyboardManagerSwift (~> 6.2.0)", "KVOController", "ObjectMapper (~> 3.1)"]
加点 pop pop (~> 1.0) 根节点
check dependency graph
["Alamofire (~> 4.7.3)", "AlamofireObjectMapper (~> 5.0)", "CocoaLumberjack/Swift", "DeviceKit (~> 2.0)", "ESTabBarController-swift", "FLEX (~> 2.0)", "IQKeyboardManagerSwift (~> 6.2.0)", "KVOController", "ObjectMapper (~> 3.1)", "pop (~> 1.0)"]
加点 Reveal-SDK Reveal-SDK (from `Reveal`) 根节点
check dependency graph
["Alamofire (~> 4.7.3)", "AlamofireObjectMapper (~> 5.0)", "CocoaLumberjack/Swift", "DeviceKit (~> 2.0)", "ESTabBarController-swift", "FLEX (~> 2.0)", "IQKeyboardManagerSwift (~> 6.2.0)", "KVOController", "ObjectMapper (~> 3.1)", "pop (~> 1.0)", "Reveal-SDK (from `Reveal`)"]
加点 SDWebImage SDWebImage (~> 4.4.6) 根节点
check dependency graph
["Alamofire (~> 4.7.3)", "AlamofireObjectMapper (~> 5.0)", "CocoaLumberjack/Swift", "DeviceKit (~> 2.0)", "ESTabBarController-swift", "FLEX (~> 2.0)", "IQKeyboardManagerSwift (~> 6.2.0)", "KVOController", "ObjectMapper (~> 3.1)", "pop (~> 1.0)", "Reveal-SDK (from `Reveal`)", "SDWebImage (~> 4.4.6)"]
加点 SnapKit SnapKit (~> 5.0.0) 根节点
check dependency graph
["Alamofire (~> 4.7.3)", "AlamofireObjectMapper (~> 5.0)", "CocoaLumberjack/Swift", "DeviceKit (~> 2.0)", "ESTabBarController-swift", "FLEX (~> 2.0)", "IQKeyboardManagerSwift (~> 6.2.0)", "KVOController", "ObjectMapper (~> 3.1)", "pop (~> 1.0)", "Reveal-SDK (from `Reveal`)", "SDWebImage (~> 4.4.6)", "SnapKit (~> 5.0.0)"]
加点 SwifterSwift SwifterSwift (~> 5.0.0) 根节点
check dependency graph
["Alamofire (~> 4.7.3)", "AlamofireObjectMapper (~> 5.0)", "CocoaLumberjack/Swift", "DeviceKit (~> 2.0)", "ESTabBarController-swift", "FLEX (~> 2.0)", "IQKeyboardManagerSwift (~> 6.2.0)", "KVOController", "ObjectMapper (~> 3.1)", "pop (~> 1.0)", "Reveal-SDK (from `Reveal`)", "SDWebImage (~> 4.4.6)", "SnapKit (~> 5.0.0)", "SwifterSwift (~> 5.0.0)"]
加点 SwiftMessages SwiftMessages (~> 6.0.2) 根节点
check dependency graph
["Alamofire (~> 4.7.3)", "AlamofireObjectMapper (~> 5.0)", "CocoaLumberjack/Swift", "DeviceKit (~> 2.0)", "ESTabBarController-swift", "FLEX (~> 2.0)", "IQKeyboardManagerSwift (~> 6.2.0)", "KVOController", "ObjectMapper (~> 3.1)", "pop (~> 1.0)", "Reveal-SDK (from `Reveal`)", "SDWebImage (~> 4.4.6)", "SnapKit (~> 5.0.0)", "SwifterSwift (~> 5.0.0)", "SwiftMessages (~> 6.0.2)"]
加点 SwiftyUserDefaults SwiftyUserDefaults 根节点
check dependency graph
["Alamofire (~> 4.7.3)", "AlamofireObjectMapper (~> 5.0)", "CocoaLumberjack/Swift", "DeviceKit (~> 2.0)", "ESTabBarController-swift", "FLEX (~> 2.0)", "IQKeyboardManagerSwift (~> 6.2.0)", "KVOController", "ObjectMapper (~> 3.1)", "pop (~> 1.0)", "Reveal-SDK (from `Reveal`)", "SDWebImage (~> 4.4.6)", "SnapKit (~> 5.0.0)", "SwifterSwift (~> 5.0.0)", "SwiftMessages (~> 6.0.2)", "SwiftyUserDefaults"]

可以看到在依赖图中不断的增加根节点。这些节点是 Podfile.lock 中的 Dependency 字段所有依赖。然后根据 Podfile.lockPods 进行完整图的构建。以下是输出测试 Log:

``ruby ["Alamofire (~> 4.7.3)", "AlamofireObjectMapper (~> 5.0)", "CocoaLumberjack/Swift", "DeviceKit (~> 2.0)", "ESTabBarController-swift", "FLEX (~> 2.0)", "IQKeyboardManagerSwift (~> 6.2.0)", "KVOController", "ObjectMapper (~> 3.1)", "pop (~> 1.0)", "Reveal-SDK (fromReveal)", "SDWebImage (~> 4.4.6)", "SnapKit (~> 5.0.0)", "SwifterSwift (~> 5.0.0)", "SwiftMessages (~> 6.0.2)", "SwiftyUserDefaults"] 加点 Alamofire 非根节点 合并版本约束 payload Alamofire (= 4.7.3, ~> 4.7.3) check dependency graph ["Alamofire (= 4.7.3, ~> 4.7.3)", "AlamofireObjectMapper (~> 5.0)", "CocoaLumberjack/Swift", "DeviceKit (~> 2.0)", "ESTabBarController-swift", "FLEX (~> 2.0)", "IQKeyboardManagerSwift (~> 6.2.0)", "KVOController", "ObjectMapper (~> 3.1)", "pop (~> 1.0)", "Reveal-SDK (fromReveal)", "SDWebImage (~> 4.4.6)", "SnapKit (~> 5.0.0)", "SwifterSwift (~> 5.0.0)", "SwiftMessages (~> 6.0.2)", "SwiftyUserDefaults"] 加点 AlamofireObjectMapper 非根节点 合并版本约束 payload AlamofireObjectMapper (= 5.2.0, ~> 5.0) 加点 Alamofire 非根节点 加边 AlamofireObjectMapper => Alamofire requirement 合并版本约束 payload Alamofire (= 4.7.3, ~> 4.7, ~> 4.7.3) 加点 ObjectMapper 非根节点 加边 AlamofireObjectMapper => ObjectMapper requirement 合并版本约束 payload ObjectMapper (~> 3.1, ~> 3.4) check dependency graph ["Alamofire (= 4.7.3, ~> 4.7, ~> 4.7.3)", "AlamofireObjectMapper (= 5.2.0, ~> 5.0)", "CocoaLumberjack/Swift", "DeviceKit (~> 2.0)", "ESTabBarController-swift", "FLEX (~> 2.0)", "IQKeyboardManagerSwift (~> 6.2.0)", "KVOController", "ObjectMapper (~> 3.1, ~> 3.4)", "pop (~> 1.0)", "Reveal-SDK (fromReveal)", "SDWebImage (~> 4.4.6)", "SnapKit (~> 5.0.0)", "SwifterSwift (~> 5.0.0)", "SwiftMessages (~> 6.0.2)", "SwiftyUserDefaults"] 加点 CocoaLumberjack/Core 非根节点 合并版本约束 payload CocoaLumberjack/Core (= 3.5.3) check dependency graph ["Alamofire (= 4.7.3, ~> 4.7, ~> 4.7.3)", "AlamofireObjectMapper (= 5.2.0, ~> 5.0)", "CocoaLumberjack/Swift", "DeviceKit (~> 2.0)", "ESTabBarController-swift", "FLEX (~> 2.0)", "IQKeyboardManagerSwift (~> 6.2.0)", "KVOController", "ObjectMapper (~> 3.1, ~> 3.4)", "pop (~> 1.0)", "Reveal-SDK (fromReveal)", "SDWebImage (~> 4.4.6)", "SnapKit (~> 5.0.0)", "SwifterSwift (~> 5.0.0)", "SwiftMessages (~> 6.0.2)", "SwiftyUserDefaults", "CocoaLumberjack/Core (= 3.5.3)"] 加点 CocoaLumberjack/Swift 非根节点 合并版本约束 payload CocoaLumberjack/Swift (= 3.5.3) 加点 CocoaLumberjack/Core 非根节点 加边 CocoaLumberjack/Swift => CocoaLumberjack/Core requirement 合并版本约束 payload CocoaLumberjack/Core (= 3.5.3) check dependency graph ["Alamofire (= 4.7.3, ~> 4.7, ~> 4.7.3)", "AlamofireObjectMapper (= 5.2.0, ~> 5.0)", "CocoaLumberjack/Swift (= 3.5.3)", "DeviceKit (~> 2.0)", "ESTabBarController-swift", "FLEX (~> 2.0)", "IQKeyboardManagerSwift (~> 6.2.0)", "KVOController", "ObjectMapper (~> 3.1, ~> 3.4)", "pop (~> 1.0)", "Reveal-SDK (fromReveal)", "SDWebImage (~> 4.4.6)", "SnapKit (~> 5.0.0)", "SwifterSwift (~> 5.0.0)", "SwiftMessages (~> 6.0.2)", "SwiftyUserDefaults", "CocoaLumberjack/Core (= 3.5.3)"] 加点 DeviceKit 非根节点 合并版本约束 payload DeviceKit (= 2.0.0, ~> 2.0) check dependency graph ["Alamofire (= 4.7.3, ~> 4.7, ~> 4.7.3)", "AlamofireObjectMapper (= 5.2.0, ~> 5.0)", "CocoaLumberjack/Swift (= 3.5.3)", "DeviceKit (= 2.0.0, ~> 2.0)", "ESTabBarController-swift", "FLEX (~> 2.0)", "IQKeyboardManagerSwift (~> 6.2.0)", "KVOController", "ObjectMapper (~> 3.1, ~> 3.4)", "pop (~> 1.0)", "Reveal-SDK (fromReveal)", "SDWebImage (~> 4.4.6)", "SnapKit (~> 5.0.0)", "SwifterSwift (~> 5.0.0)", "SwiftMessages (~> 6.0.2)", "SwiftyUserDefaults", "CocoaLumberjack/Core (= 3.5.3)"] 加点 ESTabBarController-swift 非根节点 合并版本约束 payload ESTabBarController-swift (= 2.7) check dependency graph ["Alamofire (= 4.7.3, ~> 4.7, ~> 4.7.3)", "AlamofireObjectMapper (= 5.2.0, ~> 5.0)", "CocoaLumberjack/Swift (= 3.5.3)", "DeviceKit (= 2.0.0, ~> 2.0)", "ESTabBarController-swift (= 2.7)", "FLEX (~> 2.0)", "IQKeyboardManagerSwift (~> 6.2.0)", "KVOController", "ObjectMapper (~> 3.1, ~> 3.4)", "pop (~> 1.0)", "Reveal-SDK (fromReveal)", "SDWebImage (~> 4.4.6)", "SnapKit (~> 5.0.0)", "SwifterSwift (~> 5.0.0)", "SwiftMessages (~> 6.0.2)", "SwiftyUserDefaults", "CocoaLumberjack/Core (= 3.5.3)"] 加点 FLEX 非根节点 合并版本约束 payload FLEX (= 2.4.0, ~> 2.0) check dependency graph ["Alamofire (= 4.7.3, ~> 4.7, ~> 4.7.3)", "AlamofireObjectMapper (= 5.2.0, ~> 5.0)", "CocoaLumberjack/Swift (= 3.5.3)", "DeviceKit (= 2.0.0, ~> 2.0)", "ESTabBarController-swift (= 2.7)", "FLEX (= 2.4.0, ~> 2.0)", "IQKeyboardManagerSwift (~> 6.2.0)", "KVOController", "ObjectMapper (~> 3.1, ~> 3.4)", "pop (~> 1.0)", "Reveal-SDK (fromReveal)", "SDWebImage (~> 4.4.6)", "SnapKit (~> 5.0.0)", "SwifterSwift (~> 5.0.0)", "SwiftMessages (~> 6.0.2)", "SwiftyUserDefaults", "CocoaLumberjack/Core (= 3.5.3)"] 加点 IQKeyboardManagerSwift 非根节点 合并版本约束 payload IQKeyboardManagerSwift (= 6.2.1, ~> 6.2.0) check dependency graph ["Alamofire (= 4.7.3, ~> 4.7, ~> 4.7.3)", "AlamofireObjectMapper (= 5.2.0, ~> 5.0)", "CocoaLumberjack/Swift (= 3.5.3)", "DeviceKit (= 2.0.0, ~> 2.0)", "ESTabBarController-swift (= 2.7)", "FLEX (= 2.4.0, ~> 2.0)", "IQKeyboardManagerSwift (= 6.2.1, ~> 6.2.0)", "KVOController", "ObjectMapper (~> 3.1, ~> 3.4)", "pop (~> 1.0)", "Reveal-SDK (fromReveal)", "SDWebImage (~> 4.4.6)", "SnapKit (~> 5.0.0)", "SwifterSwift (~> 5.0.0)", "SwiftMessages (~> 6.0.2)", "SwiftyUserDefaults", "CocoaLumberjack/Core (= 3.5.3)"] 加点 KVOController 非根节点 合并版本约束 payload KVOController (= 1.2.0) check dependency graph ["Alamofire (= 4.7.3, ~> 4.7, ~> 4.7.3)", "AlamofireObjectMapper (= 5.2.0, ~> 5.0)", "CocoaLumberjack/Swift (= 3.5.3)", "DeviceKit (= 2.0.0, ~> 2.0)", "ESTabBarController-swift (= 2.7)", "FLEX (= 2.4.0, ~> 2.0)", "IQKeyboardManagerSwift (= 6.2.1, ~> 6.2.0)", "KVOController (= 1.2.0)", "ObjectMapper (~> 3.1, ~> 3.4)", "pop (~> 1.0)", "Reveal-SDK (fromReveal)", "SDWebImage (~> 4.4.6)", "SnapKit (~> 5.0.0)", "SwifterSwift (~> 5.0.0)", "SwiftMessages (~> 6.0.2)", "SwiftyUserDefaults", "CocoaLumberjack/Core (= 3.5.3)"] 加点 ObjectMapper 非根节点 合并版本约束 payload ObjectMapper (= 3.4.2, ~> 3.1, ~> 3.4) check dependency graph ["Alamofire (= 4.7.3, ~> 4.7, ~> 4.7.3)", "AlamofireObjectMapper (= 5.2.0, ~> 5.0)", "CocoaLumberjack/Swift (= 3.5.3)", "DeviceKit (= 2.0.0, ~> 2.0)", "ESTabBarController-swift (= 2.7)", "FLEX (= 2.4.0, ~> 2.0)", "IQKeyboardManagerSwift (= 6.2.1, ~> 6.2.0)", "KVOController (= 1.2.0)", "ObjectMapper (= 3.4.2, ~> 3.1, ~> 3.4)", "pop (~> 1.0)", "Reveal-SDK (fromReveal)", "SDWebImage (~> 4.4.6)", "SnapKit (~> 5.0.0)", "SwifterSwift (~> 5.0.0)", "SwiftMessages (~> 6.0.2)", "SwiftyUserDefaults", "CocoaLumberjack/Core (= 3.5.3)"] 加点 pop 非根节点 合并版本约束 payload pop (= 1.0.12, ~> 1.0) check dependency graph ["Alamofire (= 4.7.3, ~> 4.7, ~> 4.7.3)", "AlamofireObjectMapper (= 5.2.0, ~> 5.0)", "CocoaLumberjack/Swift (= 3.5.3)", "DeviceKit (= 2.0.0, ~> 2.0)", "ESTabBarController-swift (= 2.7)", "FLEX (= 2.4.0, ~> 2.0)", "IQKeyboardManagerSwift (= 6.2.1, ~> 6.2.0)", "KVOController (= 1.2.0)", "ObjectMapper (= 3.4.2, ~> 3.1, ~> 3.4)", "pop (= 1.0.12, ~> 1.0)", "Reveal-SDK (fromReveal)", "SDWebImage (~> 4.4.6)", "SnapKit (~> 5.0.0)", "SwifterSwift (~> 5.0.0)", "SwiftMessages (~> 6.0.2)", "SwiftyUserDefaults", "CocoaLumberjack/Core (= 3.5.3)"] 加点 Reveal-SDK 非根节点 合并版本约束 payload Reveal-SDK (fromReveal) check dependency graph ["Alamofire (= 4.7.3, ~> 4.7, ~> 4.7.3)", "AlamofireObjectMapper (= 5.2.0, ~> 5.0)", "CocoaLumberjack/Swift (= 3.5.3)", "DeviceKit (= 2.0.0, ~> 2.0)", "ESTabBarController-swift (= 2.7)", "FLEX (= 2.4.0, ~> 2.0)", "IQKeyboardManagerSwift (= 6.2.1, ~> 6.2.0)", "KVOController (= 1.2.0)", "ObjectMapper (= 3.4.2, ~> 3.1, ~> 3.4)", "pop (= 1.0.12, ~> 1.0)", "Reveal-SDK (fromReveal)", "SDWebImage (~> 4.4.6)", "SnapKit (~> 5.0.0)", "SwifterSwift (~> 5.0.0)", "SwiftMessages (~> 6.0.2)", "SwiftyUserDefaults", "CocoaLumberjack/Core (= 3.5.3)"] 加点 SDWebImage 非根节点 合并版本约束 payload SDWebImage (= 4.4.6, ~> 4.4.6) 加点 SDWebImage/Core 非根节点 加边 SDWebImage => SDWebImage/Core requirement 合并版本约束 payload SDWebImage/Core (= 4.4.6) check dependency graph ["Alamofire (= 4.7.3, ~> 4.7, ~> 4.7.3)", "AlamofireObjectMapper (= 5.2.0, ~> 5.0)", "CocoaLumberjack/Swift (= 3.5.3)", "DeviceKit (= 2.0.0, ~> 2.0)", "ESTabBarController-swift (= 2.7)", "FLEX (= 2.4.0, ~> 2.0)", "IQKeyboardManagerSwift (= 6.2.1, ~> 6.2.0)", "KVOController (= 1.2.0)", "ObjectMapper (= 3.4.2, ~> 3.1, ~> 3.4)", "pop (= 1.0.12, ~> 1.0)", "Reveal-SDK (fromReveal)", "SDWebImage (= 4.4.6, ~> 4.4.6)", "SnapKit (~> 5.0.0)", "SwifterSwift (~> 5.0.0)", "SwiftMessages (~> 6.0.2)", "SwiftyUserDefaults", "CocoaLumberjack/Core (= 3.5.3)", "SDWebImage/Core (= 4.4.6)"] 加点 SDWebImage/Core 非根节点 合并版本约束 payload SDWebImage/Core (= 4.4.6) check dependency graph ["Alamofire (= 4.7.3, ~> 4.7, ~> 4.7.3)", "AlamofireObjectMapper (= 5.2.0, ~> 5.0)", "CocoaLumberjack/Swift (= 3.5.3)", "DeviceKit (= 2.0.0, ~> 2.0)", "ESTabBarController-swift (= 2.7)", "FLEX (= 2.4.0, ~> 2.0)", "IQKeyboardManagerSwift (= 6.2.1, ~> 6.2.0)", "KVOController (= 1.2.0)", "ObjectMapper (= 3.4.2, ~> 3.1, ~> 3.4)", "pop (= 1.0.12, ~> 1.0)", "Reveal-SDK (fromReveal)", "SDWebImage (= 4.4.6, ~> 4.4.6)", "SnapKit (~> 5.0.0)", "SwifterSwift (~> 5.0.0)", "SwiftMessages (~> 6.0.2)", "SwiftyUserDefaults", "CocoaLumberjack/Core (= 3.5.3)", "SDWebImage/Core (= 4.4.6)"] 加点 SnapKit 非根节点 合并版本约束 payload SnapKit (= 5.0.0, ~> 5.0.0) check dependency graph ["Alamofire (= 4.7.3, ~> 4.7, ~> 4.7.3)", "AlamofireObjectMapper (= 5.2.0, ~> 5.0)", "CocoaLumberjack/Swift (= 3.5.3)", "DeviceKit (= 2.0.0, ~> 2.0)", "ESTabBarController-swift (= 2.7)", "FLEX (= 2.4.0, ~> 2.0)", "IQKeyboardManagerSwift (= 6.2.1, ~> 6.2.0)", "KVOController (= 1.2.0)", "ObjectMapper (= 3.4.2, ~> 3.1, ~> 3.4)", "pop (= 1.0.12, ~> 1.0)", "Reveal-SDK (fromReveal)", "SDWebImage (= 4.4.6, ~> 4.4.6)", "SnapKit (= 5.0.0, ~> 5.0.0)", "SwifterSwift (~> 5.0.0)", "SwiftMessages (~> 6.0.2)", "SwiftyUserDefaults", "CocoaLumberjack/Core (= 3.5.3)", "SDWebImage/Core (= 4.4.6)"] 加点 SwifterSwift 非根节点 合并版本约束 payload SwifterSwift (= 5.0.0, ~> 5.0.0) 加点 SwifterSwift/AppKit 非根节点 加边 SwifterSwift => SwifterSwift/AppKit requirement 合并版本约束 payload SwifterSwift/AppKit (= 5.0.0) 加点 SwifterSwift/CoreGraphics 非根节点 加边 SwifterSwift => SwifterSwift/CoreGraphics requirement 合并版本约束 payload SwifterSwift/CoreGraphics (= 5.0.0) 加点 SwifterSwift/CoreLocation 非根节点 加边 SwifterSwift => SwifterSwift/CoreLocation requirement 合并版本约束 payload SwifterSwift/CoreLocation (= 5.0.0) 加点 SwifterSwift/Dispatch 非根节点 加边 SwifterSwift => SwifterSwift/Dispatch requirement 合并版本约束 payload SwifterSwift/Dispatch (= 5.0.0) 加点 SwifterSwift/Foundation 非根节点 加边 SwifterSwift => SwifterSwift/Foundation requirement 合并版本约束 payload SwifterSwift/Foundation (= 5.0.0) 加点 SwifterSwift/MapKit 非根节点 加边 SwifterSwift => SwifterSwift/MapKit requirement 合并版本约束 payload SwifterSwift/MapKit (= 5.0.0) 加点 SwifterSwift/SpriteKit 非根节点 加边 SwifterSwift => SwifterSwift/SpriteKit requirement 合并版本约束 payload SwifterSwift/SpriteKit (= 5.0.0) 加点 SwifterSwift/SwiftStdlib 非根节点 加边 SwifterSwift => SwifterSwift/SwiftStdlib requirement 合并版本约束 payload SwifterSwift/SwiftStdlib (= 5.0.0) 加点 SwifterSwift/UIKit 非根节点 加边 SwifterSwift => SwifterSwift/UIKit requirement 合并版本约束 payload SwifterSwift/UIKit (= 5.0.0) check dependency graph ["Alamofire (= 4.7.3, ~> 4.7, ~> 4.7.3)", "AlamofireObjectMapper (= 5.2.0, ~> 5.0)", "CocoaLumberjack/Swift (= 3.5.3)", "DeviceKit (= 2.0.0, ~> 2.0)", "ESTabBarController-swift (= 2.7)", "FLEX (= 2.4.0, ~> 2.0)", "IQKeyboardManagerSwift (= 6.2.1, ~> 6.2.0)", "KVOController (= 1.2.0)", "ObjectMapper (= 3.4.2, ~> 3.1, ~> 3.4)", "pop (= 1.0.12, ~> 1.0)", "Reveal-SDK (fromReveal)", "SDWebImage (= 4.4.6, ~> 4.4.6)", "SnapKit (= 5.0.0, ~> 5.0.0)", "SwifterSwift (= 5.0.0, ~> 5.0.0)", "SwiftMessages (~> 6.0.2)", "SwiftyUserDefaults", "CocoaLumberjack/Core (= 3.5.3)", "SDWebImage/Core (= 4.4.6)", "SwifterSwift/AppKit (= 5.0.0)", "SwifterSwift/CoreGraphics (= 5.0.0)", "SwifterSwift/CoreLocation (= 5.0.0)", "SwifterSwift/Dispatch (= 5.0.0)", "SwifterSwift/Foundation (= 5.0.0)", "SwifterSwift/MapKit (= 5.0.0)", "SwifterSwift/SpriteKit (= 5.0.0)", "SwifterSwift/SwiftStdlib (= 5.0.0)", "SwifterSwift/UIKit (= 5.0.0)"] 加点 SwifterSwift/AppKit 非根节点 合并版本约束 payload SwifterSwift/AppKit (= 5.0.0) check dependency graph ["Alamofire (= 4.7.3, ~> 4.7, ~> 4.7.3)", "AlamofireObjectMapper (= 5.2.0, ~> 5.0)", "CocoaLumberjack/Swift (= 3.5.3)", "DeviceKit (= 2.0.0, ~> 2.0)", "ESTabBarController-swift (= 2.7)", "FLEX (= 2.4.0, ~> 2.0)", "IQKeyboardManagerSwift (= 6.2.1, ~> 6.2.0)", "KVOController (= 1.2.0)", "ObjectMapper (= 3.4.2, ~> 3.1, ~> 3.4)", "pop (= 1.0.12, ~> 1.0)", "Reveal-SDK (fromReveal)", "SDWebImage (= 4.4.6, ~> 4.4.6)", "SnapKit (= 5.0.0, ~> 5.0.0)", "SwifterSwift (= 5.0.0, ~> 5.0.0)", "SwiftMessages (~> 6.0.2)", "SwiftyUserDefaults", "CocoaLumberjack/Core (= 3.5.3)", "SDWebImage/Core (= 4.4.6)", "SwifterSwift/AppKit (= 5.0.0)", "SwifterSwift/CoreGraphics (= 5.0.0)", "SwifterSwift/CoreLocation (= 5.0.0)", "SwifterSwift/Dispatch (= 5.0.0)", "SwifterSwift/Foundation (= 5.0.0)", "SwifterSwift/MapKit (= 5.0.0)", "SwifterSwift/SpriteKit (= 5.0.0)", "SwifterSwift/SwiftStdlib (= 5.0.0)", "SwifterSwift/UIKit (= 5.0.0)"] 加点 SwifterSwift/CoreGraphics 非根节点 合并版本约束 payload SwifterSwift/CoreGraphics (= 5.0.0) check dependency graph ["Alamofire (= 4.7.3, ~> 4.7, ~> 4.7.3)", "AlamofireObjectMapper (= 5.2.0, ~> 5.0)", "CocoaLumberjack/Swift (= 3.5.3)", "DeviceKit (= 2.0.0, ~> 2.0)", "ESTabBarController-swift (= 2.7)", "FLEX (= 2.4.0, ~> 2.0)", "IQKeyboardManagerSwift (= 6.2.1, ~> 6.2.0)", "KVOController (= 1.2.0)", "ObjectMapper (= 3.4.2, ~> 3.1, ~> 3.4)", "pop (= 1.0.12, ~> 1.0)", "Reveal-SDK (fromReveal)", "SDWebImage (= 4.4.6, ~> 4.4.6)", "SnapKit (= 5.0.0, ~> 5.0.0)", "SwifterSwift (= 5.0.0, ~> 5.0.0)", "SwiftMessages (~> 6.0.2)", "SwiftyUserDefaults", "CocoaLumberjack/Core (= 3.5.3)", "SDWebImage/Core (= 4.4.6)", "SwifterSwift/AppKit (= 5.0.0)", "SwifterSwift/CoreGraphics (= 5.0.0)", "SwifterSwift/CoreLocation (= 5.0.0)", "SwifterSwift/Dispatch (= 5.0.0)", "SwifterSwift/Foundation (= 5.0.0)", "SwifterSwift/MapKit (= 5.0.0)", "SwifterSwift/SpriteKit (= 5.0.0)", "SwifterSwift/SwiftStdlib (= 5.0.0)", "SwifterSwift/UIKit (= 5.0.0)"] 加点 SwifterSwift/CoreLocation 非根节点 合并版本约束 payload SwifterSwift/CoreLocation (= 5.0.0) check dependency graph ["Alamofire (= 4.7.3, ~> 4.7, ~> 4.7.3)", "AlamofireObjectMapper (= 5.2.0, ~> 5.0)", "CocoaLumberjack/Swift (= 3.5.3)", "DeviceKit (= 2.0.0, ~> 2.0)", "ESTabBarController-swift (= 2.7)", "FLEX (= 2.4.0, ~> 2.0)", "IQKeyboardManagerSwift (= 6.2.1, ~> 6.2.0)", "KVOController (= 1.2.0)", "ObjectMapper (= 3.4.2, ~> 3.1, ~> 3.4)", "pop (= 1.0.12, ~> 1.0)", "Reveal-SDK (fromReveal)", "SDWebImage (= 4.4.6, ~> 4.4.6)", "SnapKit (= 5.0.0, ~> 5.0.0)", "SwifterSwift (= 5.0.0, ~> 5.0.0)", "SwiftMessages (~> 6.0.2)", "SwiftyUserDefaults", "CocoaLumberjack/Core (= 3.5.3)", "SDWebImage/Core (= 4.4.6)", "SwifterSwift/AppKit (= 5.0.0)", "SwifterSwift/CoreGraphics (= 5.0.0)", "SwifterSwift/CoreLocation (= 5.0.0)", "SwifterSwift/Dispatch (= 5.0.0)", "SwifterSwift/Foundation (= 5.0.0)", "SwifterSwift/MapKit (= 5.0.0)", "SwifterSwift/SpriteKit (= 5.0.0)", "SwifterSwift/SwiftStdlib (= 5.0.0)", "SwifterSwift/UIKit (= 5.0.0)"] 加点 SwifterSwift/Dispatch 非根节点 合并版本约束 payload SwifterSwift/Dispatch (= 5.0.0) check dependency graph ["Alamofire (= 4.7.3, ~> 4.7, ~> 4.7.3)", "AlamofireObjectMapper (= 5.2.0, ~> 5.0)", "CocoaLumberjack/Swift (= 3.5.3)", "DeviceKit (= 2.0.0, ~> 2.0)", "ESTabBarController-swift (= 2.7)", "FLEX (= 2.4.0, ~> 2.0)", "IQKeyboardManagerSwift (= 6.2.1, ~> 6.2.0)", "KVOController (= 1.2.0)", "ObjectMapper (= 3.4.2, ~> 3.1, ~> 3.4)", "pop (= 1.0.12, ~> 1.0)", "Reveal-SDK (fromReveal)", "SDWebImage (= 4.4.6, ~> 4.4.6)", "SnapKit (= 5.0.0, ~> 5.0.0)", "SwifterSwift (= 5.0.0, ~> 5.0.0)", "SwiftMessages (~> 6.0.2)", "SwiftyUserDefaults", "CocoaLumberjack/Core (= 3.5.3)", "SDWebImage/Core (= 4.4.6)", "SwifterSwift/AppKit (= 5.0.0)", "SwifterSwift/CoreGraphics (= 5.0.0)", "SwifterSwift/CoreLocation (= 5.0.0)", "SwifterSwift/Dispatch (= 5.0.0)", "SwifterSwift/Foundation (= 5.0.0)", "SwifterSwift/MapKit (= 5.0.0)", "SwifterSwift/SpriteKit (= 5.0.0)", "SwifterSwift/SwiftStdlib (= 5.0.0)", "SwifterSwift/UIKit (= 5.0.0)"] 加点 SwifterSwift/Foundation 非根节点 合并版本约束 payload SwifterSwift/Foundation (= 5.0.0) check dependency graph ["Alamofire (= 4.7.3, ~> 4.7, ~> 4.7.3)", "AlamofireObjectMapper (= 5.2.0, ~> 5.0)", "CocoaLumberjack/Swift (= 3.5.3)", "DeviceKit (= 2.0.0, ~> 2.0)", "ESTabBarController-swift (= 2.7)", "FLEX (= 2.4.0, ~> 2.0)", "IQKeyboardManagerSwift (= 6.2.1, ~> 6.2.0)", "KVOController (= 1.2.0)", "ObjectMapper (= 3.4.2, ~> 3.1, ~> 3.4)", "pop (= 1.0.12, ~> 1.0)", "Reveal-SDK (fromReveal)", "SDWebImage (= 4.4.6, ~> 4.4.6)", "SnapKit (= 5.0.0, ~> 5.0.0)", "SwifterSwift (= 5.0.0, ~> 5.0.0)", "SwiftMessages (~> 6.0.2)", "SwiftyUserDefaults", "CocoaLumberjack/Core (= 3.5.3)", "SDWebImage/Core (= 4.4.6)", "SwifterSwift/AppKit (= 5.0.0)", "SwifterSwift/CoreGraphics (= 5.0.0)", "SwifterSwift/CoreLocation (= 5.0.0)", "SwifterSwift/Dispatch (= 5.0.0)", "SwifterSwift/Foundation (= 5.0.0)", "SwifterSwift/MapKit (= 5.0.0)", "SwifterSwift/SpriteKit (= 5.0.0)", "SwifterSwift/SwiftStdlib (= 5.0.0)", "SwifterSwift/UIKit (= 5.0.0)"] 加点 SwifterSwift/MapKit 非根节点 合并版本约束 payload SwifterSwift/MapKit (= 5.0.0) check dependency graph ["Alamofire (= 4.7.3, ~> 4.7, ~> 4.7.3)", "AlamofireObjectMapper (= 5.2.0, ~> 5.0)", "CocoaLumberjack/Swift (= 3.5.3)", "DeviceKit (= 2.0.0, ~> 2.0)", "ESTabBarController-swift (= 2.7)", "FLEX (= 2.4.0, ~> 2.0)", "IQKeyboardManagerSwift (= 6.2.1, ~> 6.2.0)", "KVOController (= 1.2.0)", "ObjectMapper (= 3.4.2, ~> 3.1, ~> 3.4)", "pop (= 1.0.12, ~> 1.0)", "Reveal-SDK (fromReveal)", "SDWebImage (= 4.4.6, ~> 4.4.6)", "SnapKit (= 5.0.0, ~> 5.0.0)", "SwifterSwift (= 5.0.0, ~> 5.0.0)", "SwiftMessages (~> 6.0.2)", "SwiftyUserDefaults", "CocoaLumberjack/Core (= 3.5.3)", "SDWebImage/Core (= 4.4.6)", "SwifterSwift/AppKit (= 5.0.0)", "SwifterSwift/CoreGraphics (= 5.0.0)", "SwifterSwift/CoreLocation (= 5.0.0)", "SwifterSwift/Dispatch (= 5.0.0)", "SwifterSwift/Foundation (= 5.0.0)", "SwifterSwift/MapKit (= 5.0.0)", "SwifterSwift/SpriteKit (= 5.0.0)", "SwifterSwift/SwiftStdlib (= 5.0.0)", "SwifterSwift/UIKit (= 5.0.0)"] 加点 SwifterSwift/SpriteKit 非根节点 合并版本约束 payload SwifterSwift/SpriteKit (= 5.0.0) check dependency graph ["Alamofire (= 4.7.3, ~> 4.7, ~> 4.7.3)", "AlamofireObjectMapper (= 5.2.0, ~> 5.0)", "CocoaLumberjack/Swift (= 3.5.3)", "DeviceKit (= 2.0.0, ~> 2.0)", "ESTabBarController-swift (= 2.7)", "FLEX (= 2.4.0, ~> 2.0)", "IQKeyboardManagerSwift (= 6.2.1, ~> 6.2.0)", "KVOController (= 1.2.0)", "ObjectMapper (= 3.4.2, ~> 3.1, ~> 3.4)", "pop (= 1.0.12, ~> 1.0)", "Reveal-SDK (fromReveal)", "SDWebImage (= 4.4.6, ~> 4.4.6)", "SnapKit (= 5.0.0, ~> 5.0.0)", "SwifterSwift (= 5.0.0, ~> 5.0.0)", "SwiftMessages (~> 6.0.2)", "SwiftyUserDefaults", "CocoaLumberjack/Core (= 3.5.3)", "SDWebImage/Core (= 4.4.6)", "SwifterSwift/AppKit (= 5.0.0)", "SwifterSwift/CoreGraphics (= 5.0.0)", "SwifterSwift/CoreLocation (= 5.0.0)", "SwifterSwift/Dispatch (= 5.0.0)", "SwifterSwift/Foundation (= 5.0.0)", "SwifterSwift/MapKit (= 5.0.0)", "SwifterSwift/SpriteKit (= 5.0.0)", "SwifterSwift/SwiftStdlib (= 5.0.0)", "SwifterSwift/UIKit (= 5.0.0)"] 加点 SwifterSwift/SwiftStdlib 非根节点 合并版本约束 payload SwifterSwift/SwiftStdlib (= 5.0.0) check dependency graph ["Alamofire (= 4.7.3, ~> 4.7, ~> 4.7.3)", "AlamofireObjectMapper (= 5.2.0, ~> 5.0)", "CocoaLumberjack/Swift (= 3.5.3)", "DeviceKit (= 2.0.0, ~> 2.0)", "ESTabBarController-swift (= 2.7)", "FLEX (= 2.4.0, ~> 2.0)", "IQKeyboardManagerSwift (= 6.2.1, ~> 6.2.0)", "KVOController (= 1.2.0)", "ObjectMapper (= 3.4.2, ~> 3.1, ~> 3.4)", "pop (= 1.0.12, ~> 1.0)", "Reveal-SDK (fromReveal)", "SDWebImage (= 4.4.6, ~> 4.4.6)", "SnapKit (= 5.0.0, ~> 5.0.0)", "SwifterSwift (= 5.0.0, ~> 5.0.0)", "SwiftMessages (~> 6.0.2)", "SwiftyUserDefaults", "CocoaLumberjack/Core (= 3.5.3)", "SDWebImage/Core (= 4.4.6)", "SwifterSwift/AppKit (= 5.0.0)", "SwifterSwift/CoreGraphics (= 5.0.0)", "SwifterSwift/CoreLocation (= 5.0.0)", "SwifterSwift/Dispatch (= 5.0.0)", "SwifterSwift/Foundation (= 5.0.0)", "SwifterSwift/MapKit (= 5.0.0)", "SwifterSwift/SpriteKit (= 5.0.0)", "SwifterSwift/SwiftStdlib (= 5.0.0)", "SwifterSwift/UIKit (= 5.0.0)"] 加点 SwifterSwift/UIKit 非根节点 合并版本约束 payload SwifterSwift/UIKit (= 5.0.0) check dependency graph ["Alamofire (= 4.7.3, ~> 4.7, ~> 4.7.3)", "AlamofireObjectMapper (= 5.2.0, ~> 5.0)", "CocoaLumberjack/Swift (= 3.5.3)", "DeviceKit (= 2.0.0, ~> 2.0)", "ESTabBarController-swift (= 2.7)", "FLEX (= 2.4.0, ~> 2.0)", "IQKeyboardManagerSwift (= 6.2.1, ~> 6.2.0)", "KVOController (= 1.2.0)", "ObjectMapper (= 3.4.2, ~> 3.1, ~> 3.4)", "pop (= 1.0.12, ~> 1.0)", "Reveal-SDK (fromReveal`)", "SDWebImage (= 4.4.6, ~> 4.4.6)", "SnapKit (= 5.0.0, ~> 5.0.0)", "SwifterSwift (= 5.0.0, ~> 5.0.0)", "SwiftMessages (~> 6.0.2)", "SwiftyUserDefaults", "CocoaLumberjack/Core (= 3.5.3)", "SDWebImage/Core (= 4.4.6)", "SwifterSwift/AppKit (= 5.0.0)", "SwifterSwift/CoreGraphics (= 5.0.0)", "SwifterSwift/CoreLocation (= 5.0.0)", "SwifterSwift/Dispatch (= 5.0.0)", "SwifterSwift/Foundation (= 5.0.0)", "SwifterSwift/MapKit (= 5.0.0)", "SwifterSwift/SpriteKit (= 5.0.0)", "SwifterSwift/SwiftStdlib (= 5.0.0)", "SwifterSwift/UIKit (= 5.0.0)"]
加点 SwiftMessages 非根节点

top Created with Sketch.