我有一个应用程序,是在Xcode 3中开发的,并最近开始在Xcode 4中进行编辑。在目标概要中,我有iOS应用程序目标形式的字段:标识符、版本、构建、设备和部署目标。版本字段为空,构建字段为3.4.0(与我仍在使用Xcode 3进行编辑时应用程序的版本相匹配)。
我的问题是:
版本字段和构建字段之间有什么区别?
为什么我升级到Xcode 4后版本字段为空?
苹果公司重新排列/重定义了这些字段。
今后,如果您在应用程序目标的“信息”选项卡上查看,您应该将“Bundle versions string, short”用作您的版本(例如3.4.0),并将“Bundle version”用作您的构建版本(例如500或1A500)。如果您没有看到它们两个,可以添加它们。它们将映射到“摘要”选项卡上的适当版本和构建文本框;它们是相同的值。
在查看“信息”选项卡时,如果您右键单击并选择显示原始键/值,您将看到实际名称是CFBundleShortVersionString
(版本)和CFBundleVersion
(构建)。
通常情况下,版本通常与Xcode 3一样使用。我不确定您关于版本/构建差异的问题提出了什么水平,因此我将从哲学的角度回答。
有各种方案,但流行的方案之一是:
{MajorVersion}.{MinorVersion}.{Revision}
然后,构建单独用于指示发布或整个产品生命周期的总构建数。
许多开发人员从0开始构建编号,并且每次构建时将数字增加1,不断增加。在我的项目中,我有一个脚本,可以在每次构建时自动增加版本号。请参见下面的说明。
其他开发人员(包括苹果)具有由主要版本+次要版本+发布的构建数量组成的构建号。这些是实际的软件版本号,而不是用于营销的值。
如果您转到Xcode菜单 > 关于Xcode,您将看到版本和构建号码。如果您点击更多信息…按钮,则会查看不同版本的多个版本。自Xcode 5起,由于删除了更多信息…按钮,因此此信息也可以从系统信息应用程序的软件 > 开发人员部分中获得,可通过打开Apple菜单 > 关于此Mac > 系统报告…获得。
例如,Xcode 4.2(4C139)。营销版本4.2的Build主要版本为4,Build次要版本为C,Build编号为139。下一个版本(可能是4.3)将很可能是Build发布4D,并且Build编号将从0开始递增。iPhone模拟器版本/Build号也是如此,iPhone、Mac等也是如此。
更新:按照需求,以下是创建脚本的步骤,该脚本在每次在Xcode中构建应用程序时运行,可以读取Build编号并将其递增,然后将其写回应用程序的{App}-Info.plist
文件。如果您想将您的版本/Build号写入您的Settings.bundle/Root*.plist
文件中,则可以执行可选的其他步骤。
这是从此处的教程文章中扩展来的。
在Xcode 4.2-5.0中:
/bin/bash
。将以下内容复制并粘贴到整数构建编号的脚本区域中:
buildNumber=$(/usr/libexec/PlistBuddy -c "Print CFBundleVersion" "$INFOPLIST_FILE")
buildNumber=$(($buildNumber + 1))
/usr/libexec/PlistBuddy -c "Set :CFBundleVersion $buildNumber" "$INFOPLIST_FILE"
如@Bdebeez所指出的,苹果通用版本控制工具(agvtool)也可用。如果您更喜欢使用它,则需要先执行以下几个步骤:
请注意,使用agvtool
方法仍然可能会定期出现失败/取消的构建,并且没有错误。出于这个原因,我不建议使用此脚本与agvtool
一起使用。
尽管如此,在您的运行脚本阶段,您可以使用以下脚本:
"${DEVELOPER_BIN_DIR}/agvtool" next-version -all
next-version
参数增加构建号(bump
是同样的别名),-all
更新 Info.plist
中的新构建号。如果您有一个显示版本和构建的设置包,则可以在脚本末尾添加以下内容以更新版本和构建。注意:更改 PreferenceSpecifiers
值以匹配您的设置。 PreferenceSpecifiers:2
表示查看 plist 文件中 PreferenceSpecifiers
数组下标为 2 的项目,因此对于基于 0 的索引,这是数组中第三个首选项设置。
productVersion=$(/usr/libexec/PlistBuddy -c "Print CFBundleShortVersionString" "$INFOPLIST_FILE")
/usr/libexec/PlistBuddy -c "Set PreferenceSpecifiers:2:DefaultValue $buildNumber" Settings.bundle/Root.plist
/usr/libexec/PlistBuddy -c "Set PreferenceSpecifiers:1:DefaultValue $productVersion" Settings.bundle/Root.plist
如果您使用agvtool
而不是直接读取Info.plist
,则可以将以下内容添加到脚本中:
buildNumber=$("${DEVELOPER_BIN_DIR}/agvtool" what-version -terse)
productVersion=$("${DEVELOPER_BIN_DIR}/agvtool" what-marketing-version -terse1)
/usr/libexec/PlistBuddy -c "Set PreferenceSpecifiers:2:DefaultValue $buildNumber" Settings.bundle/Root.plist
/usr/libexec/PlistBuddy -c "Set PreferenceSpecifiers:1:DefaultValue $productVersion" Settings.bundle/Root.plist
如果您拥有适用于iPad和iPhone的通用应用程序,那么您也可以为iPhone文件设置设置: /usr/libexec/PlistBuddy -c "Set PreferenceSpecifiers:2:DefaultValue $buildNumber" Settings.bundle/Root~iphone.plist
/usr/libexec/PlistBuddy -c "Set PreferenceSpecifiers:1:DefaultValue $productVersion" Settings.bundle/Root~iphone.plist
buildNumber=$(/usr/libexec/PlistBuddy -c "Print CFBundleVersion" "$INFOPLIST_FILE")
dec=$((0x$buildNumber))
buildNumber=$(($dec + 1))
hex=$(printf "%X" $buildNumber)
/usr/libexec/PlistBuddy -c "Set :CFBundleVersion $hex" "$INFOPLIST_FILE"
иҜ·жіЁж„ҸпјҢжӯӨд»Јз Ғе°ҶиҺ·еҸ–дёҖдёӘеҚҒе…ӯиҝӣеҲ¶ж•°пјҢе°Ҷе…¶иҪ¬жҚўдёәеҚҒиҝӣеҲ¶ж•°еӯ—пјҢйҖ’еўһдёҖпјҢ并е°Ҷз»“жһңиҪ¬жҚўеӣһеҚҒе…ӯиҝӣеҲ¶гҖӮжңҖеҗҺпјҢе®ғе°ҶдҪҝз”Ё PlistBuddy е‘Ҫд»Өжӣҙж–° INFOPLIST_FILE дёӯзҡ„ CFBundleVersionгҖӮ - Alon Amir(我只是为了自己的参考而留下这个。)这将显示Xcode目标中您看到的“版本”和“构建”字段的版本和构建:
- (NSString*) version {
NSString *version = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleShortVersionString"];
NSString *build = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleVersion"];
return [NSString stringWithFormat:@"%@ build %@", version, build];
}
在Swift中
func version() -> String {
let dictionary = NSBundle.mainBundle().infoDictionary!
let version = dictionary["CFBundleShortVersionString"] as? String
let build = dictionary["CFBundleVersion"] as? String
return "\(version) build \(build)"
}
alloc
/init
来初始化字符串,这将导致字符串被保留,但是你没有释放它。对于从方法返回的对象,通常应该使用一个 convenience 方法来让字符串自动释放,或者调用 autorelease
。可以选择以下两种方式中的一种:return [NSString stringWithFormat:@"%@ build %@", version, build];
或者 return [[[NSString alloc] initWithFormat:@"%@ build %@", version, build] autorelease];
- neknoBuild number是一个内部编号,表示应用程序的当前状态。 它与版本号不同,通常不面向用户,并且不表示任何差异/功能/升级,就像版本号通常会做的那样。
可以这样想:
CFBundleVersion
):构建的数量。 通常情况下,您从1开始,并随着每个应用程序的构建而增加1。 它快速允许比较哪个版本更近,并表示代码库的进展感。在与QA一起工作并需要确保错误日志记录在正确的构建中时,这些可能非常有价值。CFBundleShortVersionString
):您正在使用的面向用户的数字,以表示应用程序的此版本。 通常,这遵循Major.minor版本方案(例如MyAwesomeApp 1.2),以让用户知道哪些发布是较小的维护更新,哪些是重大的新功能。为了在项目中有效地使用它,苹果提供了一个很棒的工具,称为agvtool
。 我强烈建议使用它,因为它比编写plist更改要简单得多。 它允许您轻松设置构建号和营销版本。 当脚本化(例如,在每个构建中轻松更新构建号,甚至查询当前构建号是什么)时,它特别有用。 它甚至可以做更多奇异的事情,比如在更新生成号时为您标记SVN。
使用方法:
agvtool new-version 1
(将生成号设置为1)agvtool new-marketing-version 1.0
(将营销版本设置为1.0)请参见agvtool
的man页面以获取大量有用信息
我从stackoverflow获取了一个自动增加构建号的脚本,但是如果构建号是浮点数,那么上面答案中的脚本就没有用了,因此我进行了一些修改:
#!/bin/bash
buildNumber=$(/usr/libexec/PlistBuddy -c "Print CFBundleVersion" "$INFOPLIST_FILE")
buildNumber=`echo $buildNumber +1|bc`
/usr/libexec/PlistBuddy -c "Set :CFBundleVersion $buildNumber" "$INFOPLIST_FILE"
营销发布号码是针对客户的,称为版本号。它以1.0开始,并在主要更新时增加到2.0、3.0,在次要更新时增加到1.1、1.2,在修复错误时增加到1.0.1、1.0.2。此编号围绕发行版和新功能。
构建号码大多是迄今为止制作的内部构建号码。但有些人使用其他数字,如存储库的分支号码。该数字应该是唯一的,以区分不同的几乎相同的构建版本。
正如您所看到的,构建号码并不是必需的,您可以选择使用哪个构建号码。因此,如果您将Xcode
更新到主要版本,则构建字段为空。但版本字段可能不为空!
要将build
号码作为NSString
变量获取:
NSString * appBuildString = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleVersion"];
要将版本号作为NSString
变量获取:
NSString * appVersionString = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleShortVersionString"];
如果你想在一个NSString
中同时获取两者:
NSString * versionBuildString = [NSString stringWithFormat:@"Version: %@ (%@)", appVersionString, appBuildString];
这是使用 Xcode版本4.6.3(4H1503) 进行的测试。构建号通常用括号/花括号括起来。构建号可以是十六进制或十进制。
在 Xcode 中,您可以通过在项目设置中的 Run script
构建阶段中添加以下内容来自动递增 十进制的构建号:
#!/bin/bash
buildNumber=$(/usr/libexec/PlistBuddy -c "Print CFBundleVersion" "$INFOPLIST_FILE")
buildNumber=$(($buildNumber + 1))
/usr/libexec/PlistBuddy -c "Set :CFBundleVersion $buildNumber" "$INFOPLIST_FILE"
使用此脚本来生成十六进制版本号
buildNumber=$(/usr/libexec/PlistBuddy -c "Print CFBundleVersion" "$INFOPLIST_FILE")
buildNumber=$((0x$buildNumber))
buildNumber=$(($buildNumber + 1))
buildNumber=$(printf "%X" $buildNumber)
/usr/libexec/PlistBuddy -c "Set :CFBundleVersion $buildNumber" "$INFOPLIST_FILE"
感谢 @nekno 和 @ale84 提供了很好的答案。
然而,我稍微修改了 @ale84 的脚本,使它可以对浮点数增加构建号。
incl 的值可以根据您的浮点格式要求进行更改。 例如:如果 incl = .01,则输出格式将为 ... 1.19, 1.20, 1.21 ...
buildNumber=$(/usr/libexec/PlistBuddy -c "Print CFBundleVersion" "$INFOPLIST_FILE")
incl=.01
buildNumber=`echo $buildNumber + $incl|bc`
/usr/libexec/PlistBuddy -c "Set :CFBundleVersion $buildNumber" "$INFOPLIST_FILE"
currentVersionString=$(/usr/libexec/PlistBuddy -c "Print CFBundleShortVersionString" "$PROJECT_DIR/SupportingFiles/$INFOPLIST_FILE")
currentBuildNumber=$(/usr/libexec/PlistBuddy -c "Print CFBundleVersion" "$PROJECT_DIR/SupportingFiles/$INFOPLIST_FILE")
newBuildNumber=$((currentBuildNumber + 1))
IFS='.' read -ra version <<< "$currentVersionString"
version[2]=$((version[2] + 1))
newVersionString="${version[0]}.${version[1]}.${version[2]}"
/usr/libexec/PlistBuddy -c "Set :CFBundleShortVersionString $newVersionString" "$PROJECT_DIR/SupportingFiles/$INFOPLIST_FILE"
/usr/libexec/PlistBuddy -c "Set :CFBundleVersion $newBuildNumber" "$PROJECT_DIR/SupportingFiles/$INFOPLIST_FILE"
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
NSString * ver = [self myVersion];
NSLog(@"version: %@",ver);
NSUserDefaults* userDefaults = [NSUserDefaults standardUserDefaults];
[userDefaults setObject:ver forKey:@"version"];
return YES;
}
- (NSString *) myVersion {
NSString *version = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleShortVersionString"];
NSString *build = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleVersion"];
return [NSString stringWithFormat:@"%@ build %@", version, build];
}