【问题标题】:What is the best way to get a specific CocoaPod's version at runtime?在运行时获取特定 CocoaPods 版本的最佳方法是什么?
【发布时间】:2016-11-13 01:07:07
【问题描述】:

我目前正在尝试创建一种方法来在运行时记录我的 Pod 的当前版本,我想到了几种方法,但我想在这里询问以确保我没有遗漏一些明显的东西。

到目前为止我做了什么:

  • 发现 Cocoapods 生成了一个myPod-umbrella.h 头文件,导出以下内容:

    FOUNDATION_EXPORT double myPodVersionNumber;
    FOUNDATION_EXPORT const unsigned char myPodVersionString[];
    

    他们只有myPodVersionNumber 似乎可以访问,并且由于某种原因它总是有 1.0,有没有办法让它正常工作,因为我觉得这是正确的方法,但我配置错误。

  • 尝试获取已构建框架的 Info.plist 并在那里读取版本,但这似乎有点问题,我不能保证开发人员最终会用 pod 做什么并且可能会结束使用捆绑包的不同位置,甚至项目无法访问它。

  • 使用版本号创建一个硬编码的属性,这显然可行,但它增加了很多错误空间,并且感觉不是实现这一点的正确方法,但如果没有其他方法可以解决CocoaPods,我可能只需要这样做。

  • 有一个构建步骤,它将读取 PodSpec 并生成一个简单的类,其中包含有关 Pod 的元数据,感觉比前一点好一点,但对于我正在寻找的东西仍然感觉有点矫枉过正。

有没有人有更好的主意或可以指出正确的方向?

我想要实现的是能够运行这样的东西

print("Current version: \(myPod.version)")

并让它在控制台中正确注销

#Current version: 1.2.0

【问题讨论】:

  • 您是否考虑过从Podfile.lock 文件中读取数据?这列出了已安装 Pod 的所有版本。
  • 我需要在运行时这样做,这是我的主要问题

标签: ios objective-c swift cocoapods


【解决方案1】:

使用 URLForResource 怎么样?在运行时使用您要求的打印语句很好地打印。

此版本将整个锁定文件打印到控制台。

override func viewDidLoad() {
    super.viewDidLoad()

    let url = NSBundle.mainBundle().URLForResource("/lockfilefolder/Podfile", withExtension: "lock")!
    let data = try! String(contentsOfURL: url, encoding: NSUTF8StringEncoding)
    print(data)   
}

/* Prints */
// PODS:
// - Firebase/Analytics (3.3.0):
// - FirebaseAnalytics (= 3.2.1)
// - Firebase/Auth (3.3.0):
// - Firebase/Analytics (= 3.3.0)
// - FirebaseAuth (= 3.0.3)
// - Firebase/Core (3.3.0):
// - Firebase/Analytics (= 3.3.0)
// - Firebase/Database (3.3.0):
// - Firebase/Analytics (= 3.3.0)
// - FirebaseDatabase (= 3.0.2)
// TL;DR

下一个版本会打印特定的行号。通过使用 componentsSeparatedByString("-"),我可以删除 pod 名称前的 - 字符,这样看起来更干净。这是有效的,因为锁定文件在 pod 名称列表的每一行上都使用 -。请注意,我们在这里使用的是 pathForResource 而不是 URLForResource

    do {
        if let path = NSBundle.mainBundle().pathForResource("/lockfilefolder/Podfile", ofType: "lock"){
            let data = try String(contentsOfFile: path, encoding: NSUTF8StringEncoding)
            let lockFileData = data.componentsSeparatedByString("-")
            print("Current version: \(lockFileData[6])")
        }
    } catch let err as NSError {
        print(err)
    }

/* Prints */
// Current version: - Firebase/Core (3.3.0):

下一个版本我们打印两行。我们正在使用data.componentsSeparatedByCharactersInSet(NSCharacterSet.newlineCharacterSet()) 方法。在这种情况下删除- 会变得很冗长,因此不值得。

let url = NSBundle.mainBundle().URLForResource("/lockfilefolder/Podfile", withExtension: "lock")!
    let data = try! String(contentsOfURL: url, encoding: NSUTF8StringEncoding)
    let lockFileData = data.componentsSeparatedByCharactersInSet(NSCharacterSet.newlineCharacterSet())
    print(lockFileData[72])
    print(lockFileData[6])

/* Prints */
// COCOAPODS: 0.39.0
// - Firebase/Core (3.3.0):

【讨论】:

  • @mostafatorbjørnberg 你好。我的回答可以吗?该代码为您提供了一个打印语句,在运行时将您希望的任何行记录到控制台。只需将锁定文件放入您的项目中即可。
  • 嗨@tymac,感谢您的回复,听起来不错,而且肯定会起作用,但它不是一个“正确”的解决方案,它是一个似乎缺少 IMO 的东西的解决方法,我也不想将 Podfile 添加到项目中,因为它与我自己的项目没有直接关系,我希望它位于 XCode 之外,如果没有官方解决方案,我将使用解析该文件并添加的构建脚本某种podsVersions.json 文件,然后我可以在我的项目中使用
【解决方案2】:

1

let version = Bundle(for: type(of:PODClass)).object(forInfoDictionaryKey:"CFBundleShortVersionString") as? String

2

if let bundle = Bundle.allFrameworks.first(where: { $0.bundleIdentifier?.contains("POD bundleIdentifier or part") ?? false } ) {
    let version = bundle.object(forInfoDictionaryKey:"CFBundleShortVersionString") as? String
}

3

if let url = Bundle.main.resourceURL?.appendingPathComponent("Frameworks/PODName.framework") {
    let version = Bundle(url: url)?.object(forInfoDictionaryKey: "CFBundleShortVersionString") as? String
}

【讨论】:

    猜你喜欢
    • 2013-02-14
    • 1970-01-01
    • 1970-01-01
    • 2010-11-13
    • 2015-09-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多