【问题标题】:Get Cocoa Touch Framework project version string in Swift在 Swift 中获取 Cocoa Touch Framework 项目版本字符串
【发布时间】:2015-10-03 18:42:33
【问题描述】:

Cocoa Touch 框架提供版本控制支持,可以在 Versioning 部分下的Build Settings 中找到。

要在运行时访问此值,我们可以使用在构建过程中为我们自动生成的 FrameworkVersionNumberFrameworkVersionString[] 变量。

使用 Swift 项目时,可以在 Objective-C 兼容性标题的顶部自动生成这些:

//! Project version number for Framework.
FOUNDATION_EXPORT double FrameworkVersionNumber;

//! Project version string for Framework.
FOUNDATION_EXPORT const unsigned char FrameworkVersionString[];

然而,FrameworkVersionNumber 可以从 Swift 访问,FrameworkVersionString[] 不能。其实查看框架模块的内容,我可以看到只有第一个变量暴露给了 Swift:

//! Project version number for Framework.
var FrameworkVersionNumber: Double

问题在于,由于FrameworkVersionNumberDouble,因此任何版本号(如 3.2.1)都会简单地更改为 3.200000...

有谁知道这是否是我的项目设置中的一个缺陷、Xcode 中的一个错误,或者是否有办法在 Swift 中以String 或数组的形式获取框架版本,以便我可以提供更精细的版本控制比major.minor

【问题讨论】:

标签: ios objective-c xcode swift


【解决方案1】:

我实际上已经找到了解决此问题的潜在解决方法,虽然不是很干净但确实有效:

默认情况下,当 Xcode 创建一个框架时,它会将 Version 设置为 1.0 并将 Build 设置为 $(CURRENT_PROJECT_VERSION),这很好,因为这个值实际上是从 Build Settings > Versioning 中的 Current Project Version 字段复制。

所以你可以在运行时获取这个值的方法如下:

let bundle = NSBundle(identifier: "com.yourframework.Framework")! // Get a reference to the bundle from your framework (not the bundle of the app itself!)
let build = bundle.infoDictionary![kCFBundleVersionKey] as! String // Get the build from the framework's bundle as a String

这确实有效,但对于过去(我相信)可以从 Objective-C 中的变量轻松访问的东西来说感觉相当迂回。

重要更新 - 2021 年 10 月 - XCODE 13

向 App Store 提交应用时,Xcode 13 有一个名为“管理版本和内部版本号”的新选项,默认勾选。如果选中,Xcode 将自动设置您应用的版本号(相当违反直觉),也将适用于所有包含的框架。换句话说,如果您的应用版本是 1.0,您的框架版本将被 1.0 覆盖。

确保禁用此选项以避免覆盖您的框架版本。

您还可以通过在导出选项列表中设置 manageAppVersionAndBuildNumber 来选择退出此新行为。

更多详情,请参阅this discussion on the Apple Developer Forums

【讨论】:

  • 为什么Bundle(identifier: "com.yourframework.Framework") 总是返回零? (斯威夫特 4.1)
  • 对不起,如果这是一个愚蠢的问题,但只是为了检查一下,您是否将标识符更改为框架的标识符?
  • 感谢您的提示。我猜你知道这不适用于Static Framework,因为它不在应用程序的Bundle [它被编译到主二进制文件中]。
【解决方案2】:

从项目的CURRENT_PROJECT_VERSION 构建时,这些变量会填充到自动生成的 .c 文件中。它看起来像这样:

 extern const unsigned char FrameworkVersionString[];
 extern const double FrameworkVersionNumber;

 const unsigned char FrameworkVersionString[] __attribute__ ((used)) = "@(#)PROGRAM:Mark2SDK  PROJECT:Framework-1" "\n";
 const double FrameworkVersionNumber __attribute__ ((used)) = (double)1.;

由于某种原因,C 数组不能用于 Swift。将数组定义修改为指针会导致EXC_BAD_ACCESS 崩溃。你可以做的是创建一个指向数组的指针并使用它。在Framework.h:

//! Project version string for Framework.
FOUNDATION_EXPORT const unsigned char FrameworkVersionString[];
// add this
extern const unsigned char * FrameworkVersionStringPtr;

然后,通过创建 Framework.c 或在另一个 c 或 m 文件中添加:

#import "Framework.h"

const unsigned char * FrameworkVersionStringPtr = FrameworkVersionString;

然后您可以在 Swift 中使用字符串指针来获取版本:

func version() -> String? {
    let ver = String(cString: Mark2SDKVersionStringPtr)
    guard let range = ver.range(of: "-") else {
        return nil
    }
    return String(ver[range.upperBound...])
}
print(version())
// 1.0.1

【讨论】:

    【解决方案3】:

    对于 swift 4.2 它可以工作:

    if let bundle = Bundle(identifier: "com.ingconti.SampleFramework") {
           if let build = bundle.infoDictionary?["CFBundleShortVersionString"] {
               print(build)
           }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-03-06
      • 1970-01-01
      • 1970-01-01
      • 2021-09-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-06-18
      相关资源
      最近更新 更多