ios 版本与在 Xcode 中构建
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/6851660/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Version vs build in Xcode
提问by chris
I have an app that I developed with Xcode 3 and recently started editing with Xcode 4. In the target summary I have the iOS application target form with fields: identifier, version, build, devices, and deployment target. The version field is blank and the build field is 3.4.0 (which matches the version of the app from when I was still editing with Xcode 3).
我有一个使用 Xcode 3 开发的应用程序,最近开始使用 Xcode 4 进行编辑。在目标摘要中,我有一个 iOS 应用程序目标表单,其中包含以下字段:标识符、版本、构建、设备和部署目标。版本字段为空,构建字段为 3.4.0(这与我仍在使用 Xcode 3 进行编辑时的应用程序版本相匹配)。
My questions are:
我的问题是:
What is the difference between the version and build fields?
Why was the version field blank after I upgraded to Xcode 4?
version 和 build 字段之间有什么区别?
为什么升级到 Xcode 4 后版本字段为空?
回答by nekno
Apple sort of rearranged/repurposed the fields.
Apple 对这些领域进行了重新排列/重新利用。
Going forward, if you look on the Info tab for your Application Target, you should use the "Bundle versions string, short" as your Version (e.g., 3.4.0) and "Bundle version" as your Build (e.g., 500 or 1A500). If you don't see them both, you can add them. Those will map to the proper Version and Build textboxes on the Summary tab; they are the same values.
展望未来,如果您查看应用程序目标的信息选项卡,您应该使用“Bundle versions string, short”作为您的版本(例如 3.4.0)和“Bundle version”作为您的 Build(例如,500 或 1A500 )。如果您没有看到它们,您可以添加它们。这些将映射到“摘要”选项卡上的正确版本和构建文本框;它们是相同的值。
When viewing the Info tab, if you right-click and select Show Raw Keys/Values, you'll see the actual names are CFBundleShortVersionString
(Version) and CFBundleVersion
(Build).
查看信息选项卡时,如果您右键单击并选择Show Raw Keys/Values,您将看到实际名称为CFBundleShortVersionString
(Version) 和CFBundleVersion
(Build)。
The Version is usually used how you appear to have been using it with Xcode 3. I'm not sure on what level you're asking about the Version/Build difference, so I'll answer it philosophically.
版本通常用于您在 Xcode 3 中使用它的方式。我不确定您在什么级别上询问版本/构建差异,所以我会从哲学上回答它。
There are all sorts of schemes, but a popular one is:
有各种各样的方案,但一种流行的是:
{MajorVersion}.{MinorVersion}.{Revision}
{MajorVersion}.{MinorVersion}.{Revision}
- Major version- Major changes, redesigns, and functionality changes
- Minor version- Minor improvements, additions to functionality
- Revision- A patch number for bug-fixes
- 主要版本- 主要更改、重新设计和功能更改
- 小版本- 小改进,增加功能
- 修订版- 用于错误修复的补丁号
Then the Build is used separately to indicate the total number of builds for a release or for the entire product lifetime.
然后单独使用 Build 来表示一个版本或整个产品生命周期的构建总数。
Many developers start the Build number at 0, and every time they build they increase the number by one, increasing forever. In my projects, I have a script that automatically increases the build number every time I build. See instructions for that below.
许多开发人员从 0 开始构建编号,每次构建时都会将编号增加 1,并永远增加。在我的项目中,我有一个脚本,每次构建时都会自动增加构建号。请参阅下面的说明。
- Release 1.0.0 might be build 542. It took 542 builds to get to a 1.0.0 release.
- Release 1.0.1 might be build 578.
- Release 1.1.0 might be build 694.
- Release 2.0.0 might be build 949.
- 1.0.0 版可能是 542 版。需要 542 版才能获得 1.0.0 版。
- 版本 1.0.1 可能是 build 578。
- 版本 1.1.0 可能是内部版本 694。
- 2.0.0 版可能是 build 949。
Other developers, including Apple, have a Build number comprised of a major version + minor version + number of builds for the release. These are the actual software version numbers, as opposed to the values used for marketing.
包括 Apple 在内的其他开发人员的内部版本号由主要版本 + 次要版本 + 版本的内部版本号组成。这些是实际的软件版本号,而不是用于营销的值。
If you go to Xcodemenu > About Xcode, you'll see the Version and Build numbers. If you hit the More Info...button you'll see a bunch of different versions. Since the More Info...button was removed in Xcode 5, this information is also available from the Software > Developersection of the System Informationapp, available by opening Applemenu > About This Mac> System Report....
如果您转到Xcode菜单 > About Xcode,您将看到版本号和内部版本号。如果你点击更多信息...按钮,你会看到一堆不同的版本。由于在 Xcode 5 中删除了More Info...按钮,因此也可以从System Information应用程序的Software > Developer部分获得此信息,可通过打开Applemenu > About This Mac> System Report... 获得。
For example, Xcode 4.2 (4C139). Marketing version 4.2 is Build major version 4, Build minor version C, and Build number 139. The next release (presumably 4.3) will likely be Build release 4D, and the Build number will start over at 0 and increment from there.
例如,Xcode 4.2 (4C139)。营销版本 4.2 是 Build 主要版本 4、Build 次要版本 C 和 Build 号 139。下一个版本(大概是 4.3)可能是 Build 版本 4D,并且 Build 号将从 0 重新开始并从那里递增。
The iPhone Simulator Version/Build numbers are the same way, as are iPhones, Macs, etc.
iPhone 模拟器版本/内部版本号也是如此,iPhone、Mac 等也是如此。
- 3.2: (7W367a)
- 4.0: (8A400)
- 4.1: (8B117)
- 4.2: (8C134)
- 4.3: (8H7)
- 3.2:(7W367a)
- 4.0: (8A400)
- 4.1: (8B117)
- 4.2: (8C134)
- 4.3:(8H7)
Update: By request, here are the steps to create a script that runs each time you build your app in Xcode to read the Build number, increment it, and write it back to the app's {App}-Info.plist
file. There are optional, additional steps if you want to write your version/build numbers to your Settings.bundle/Root*.plist
file(s).
更新:根据要求,以下是创建脚本的步骤,该脚本每次在 Xcode 中构建应用程序时都会运行,以读取构建编号、递增它并将其写回应用程序{App}-Info.plist
文件。如果要将版本/内部版本号写入Settings.bundle/Root*.plist
文件,还有一些可选的附加步骤。
This is extended from the how-to article here.
这是从这里的操作方法文章扩展而来的。
In Xcode 4.2 - 5.0:
在 Xcode 4.2 - 5.0 中:
- Load your Xcode project.
- In the left hand pane, click on your project at the very top of the hierarchy. This will load the project settings editor.
- On the left-hand side of the center window pane, click on your app under the TARGETSheading. You will need to configure this setup for each project target.
- Select the Build Phasestab.
- In Xcode 4, at the bottom right, click the Add Build Phasebutton and select Add Run Script.
- In Xcode 5, select Editormenu > Add Build Phase> Add Run Script Build Phase.
- Drag-and-drop the new Run Scriptphase to move it to just before the Copy Bundle Resourcesphase (when the app-info.plist file will be bundled with your app).
- In the new Run Scriptphase, set Shell:
/bin/bash
. Copy and paste the following into the script area for integer build numbers:
buildNumber=$(/usr/libexec/PlistBuddy -c "Print CFBundleVersion" "$INFOPLIST_FILE") buildNumber=$(($buildNumber + 1)) /usr/libexec/PlistBuddy -c "Set :CFBundleVersion $buildNumber" "$INFOPLIST_FILE"
As @Bdebeez pointed out, the Apple Generic Versioning Tool(
agvtool
) is also available. If you prefer to use it instead, then there are a couple things to change first:- Select the Build Settingstab.
- Under the Versioningsection, set the Current Project Versionto the initial build number you want to use, e.g., 1.
- Back on the Build Phasestab, drag-and-drop your Run Scriptphase after the Copy Bundle Resourcesphase to avoid a race condition when trying to both build and update the source file that includes your build number.
Note that with the
agvtool
method you may still periodically get failed/canceled builds with no errors. For this reason, I don't recommend usingagvtool
with this script.Nevertheless, in your Run Scriptphase, you can use the following script:
"${DEVELOPER_BIN_DIR}/agvtool" next-version -all
The
next-version
argument increments the build number (bump
is also an alias for the same thing), and-all
updatesInfo.plist
with the new build number.And if you have a Settings bundle where you show the Version and Build, you can add the following to the end of the script to update the version and build. Note: Change the
PreferenceSpecifiers
values to match your settings.PreferenceSpecifiers:2
means look at the item at index 2 under thePreferenceSpecifiers
array in your plist file, so for a 0-based index, that's the 3rd preference setting in the array.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
If you're using
agvtool
instead of reading theInfo.plist
directly, you can add the following to your script instead: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
And if you have a universal app for iPad & iPhone, then you can also set the settings for the iPhone file:
/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
- 加载您的 Xcode 项目。
- 在左侧窗格中,单击层次结构最顶部的项目。这将加载项目设置编辑器。
- 在中央窗口窗格的左侧,单击TARGETS标题下的应用程序。您需要为每个项目目标配置此设置。
- 选择构建阶段选项卡。
- 在 Xcode 4 中,在右下角,单击Add Build Phase按钮并选择Add Run Script。
- 在 Xcode 5 中,选择Editormenu > Add Build Phase> Add Run Script Build Phase。
- 拖放新的Run Script阶段以将其移动到Copy Bundle Resources阶段之前(此时 app-info.plist 文件将与您的应用程序捆绑在一起)。
- 在新的运行脚本阶段,设置Shell:
/bin/bash
。 将以下内容复制并粘贴到整数内部版本号的脚本区域中:
buildNumber=$(/usr/libexec/PlistBuddy -c "Print CFBundleVersion" "$INFOPLIST_FILE") buildNumber=$(($buildNumber + 1)) /usr/libexec/PlistBuddy -c "Set :CFBundleVersion $buildNumber" "$INFOPLIST_FILE"
正如@Bdebeez 指出的那样,Apple 通用版本控制工具(
agvtool
) 也可用。如果您更喜欢使用它,那么首先需要更改几件事情:- 选择构建设置选项卡。
- 在Versioning部分下,将Current Project Version设置为您要使用的初始内部版本号,例如1。
- 返回Build Phases选项卡,在Copy Bundle Resources阶段之后拖放您的Run Script阶段,以避免在尝试构建和更新包含您的构建号的源文件时出现争用情况。
请注意,使用该
agvtool
方法,您可能仍会定期获得失败/取消的构建而没有错误。因此,我不建议使用agvtool
此脚本。不过,在您的运行脚本阶段,您可以使用以下脚本:
"${DEVELOPER_BIN_DIR}/agvtool" next-version -all
该
next-version
参数增加内部版本号(bump
也是同一事物的别名),并使用新的内部版本号进行-all
更新Info.plist
。如果您有一个显示版本和构建的设置包,您可以将以下内容添加到脚本的末尾以更新版本和构建。注意:更改
PreferenceSpecifiers
值以匹配您的设置。PreferenceSpecifiers:2
表示查看PreferenceSpecifiers
plist 文件中数组下索引 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
回答by Dan Rosenstark
(Just leaving this here for my own reference.) This will show version and build for the "version" and "build" fields you see in an Xcode target:
(只是留在这里供我自己参考。)这将显示您在 Xcode 目标中看到的“版本”和“构建”字段的版本和构建:
- (NSString*) version {
NSString *version = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleShortVersionString"];
NSString *build = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleVersion"];
return [NSString stringWithFormat:@"%@ build %@", version, build];
}
In 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)"
}
回答by Bdebeez
The Build number is an internal number that indicates the current state of the app. It differs from the Version number in that it's typically not user facing and doesn't denote any difference/features/upgrades like a version number typically would.
内部版本号是一个内部编号,表示应用程序的当前状态。它与版本号的不同之处在于它通常不是面向用户的,并且不像通常的版本号那样表示任何差异/功能/升级。
Think of it like this:
可以这样想:
- Build (
CFBundleVersion
): The number of the build. Usually you start this at 1 and increase by 1 with each build of the app. It quickly allows for comparisons of which build is more recent and it denotes the sense of progress of the codebase. These can be overwhelmingly valuable when working with QA and needing to be sure bugs are logged against the right builds. - Marketing Version (
CFBundleShortVersionString
): The user-facing number you are using to denote this version of your app. Usually this follows a Major.minor version scheme (e.g. MyAwesomeApp 1.2) to let users know which releases are smaller maintenance updates and which are big deal new features.
- Build (
CFBundleVersion
):构建的编号。通常你从 1 开始,并随着应用程序的每个构建增加 1。它可以快速比较哪个构建是较新的,它表示代码库的进度感。在使用 QA 并需要确保针对正确的构建记录错误时,这些可能非常有价值。 - 营销版本 (
CFBundleShortVersionString
):您用来表示应用程序的此版本的面向用户的编号。通常这遵循 Major.minor 版本方案(例如 MyAwesomeApp 1.2),让用户知道哪些版本是较小的维护更新,哪些是重要的新功能。
To use this effectively in your projects, Apple provides a great tool called agvtool
. I highly recommend using this as it is MUCH more simple than scripting up plist changes.It allows you to easily set both the build number and the marketing version. It is particularly useful when scripting (for instance, easily updating the build number on each build or even querying what the current build number is). It can even do more exotic things like tag your SVN for you when you update the build number.
为了在您的项目中有效地使用它,Apple 提供了一个名为agvtool
. 我强烈建议使用它,因为它比编写 plist 更改脚本简单得多。它允许您轻松设置内部版本号和营销版本。它在编写脚本时特别有用(例如,轻松更新每个构建的构建号,甚至查询当前构建号是什么)。它甚至可以做更多奇特的事情,例如在您更新内部版本号时为您标记 SVN。
To use it:
要使用它:
- Set your project in Xcode, under Versioning, to use "Apple Generic".
- In terminal
agvtool new-version 1
(set the Build number to 1)agvtool new-marketing-version 1.0
(set the Marketing version to 1.0)
- 在 Xcode 中的 Versioning 下设置您的项目以使用“Apple Generic”。
- 在终端
agvtool new-version 1
(将内部版本号设置为 1)agvtool new-marketing-version 1.0
(将营销版本设置为 1.0)
See the man page of agvtool
for a ton of good info
有关agvtool
大量好信息,请参阅手册页
回答by ale84
The script to autoincrement the build number in the answer above didn't work for me if the build number is a floating point value, so I modified it a little:
如果内部版本号是浮点值,则上面答案中自动增加内部版本号的脚本对我不起作用,因此我对其进行了一些修改:
#!/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"
回答by Binarian
The marketing release number is for the customers, called version number. It starts with 1.0and goes up for major updates to 2.0, 3.0, for minor updates to 1.1, 1.2and for bug fixes to 1.0.1, 1.0.2. This number is oriented about releases and new features.
营销版本号是针对客户的,称为版本号。它从1.0开始,随着对2.0、3.0 的主要更新、对1.1、1.2 的次要更新以及对1.0.1、1.0.2 的错误修复而上升。这个数字是关于发布和新功能的。
The build numberis mostly the internal number of buildsthat have been made until then. But some use other numbers like the branch number of the repository. This number should be uniqueto distinguish the different nearly the same builds.
该版本号是大多是内部号码的建立已取得直到那时。但有些使用其他数字,如存储库的分支编号。这个数字应该是唯一的,以区分几乎相同的不同版本。
As you can see, the build numberis not necessary and it is up to you which build numberyou want to use. So if you update your Xcode
to a major version, the buildfield is empty. The versionfield may not be empty!.
如您所见,内部版本号不是必需的,由您决定要使用哪个内部版本号。因此,如果您将您Xcode
的版本更新为主要版本,则构建字段为空。该版本字段不能为空!
To get the buildnumber as a NSString
variable:
获取内部版本号作为NSString
变量:
NSString * appBuildString = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleVersion"];
To get the versionnumber as a NSString
variable:
获取版本号作为NSString
变量:
NSString * appVersionString = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleShortVersionString"];
If you want bothin one NSString
:
如果你想要两者合二为一NSString
:
NSString * versionBuildString = [NSString stringWithFormat:@"Version: %@ (%@)", appVersionString, appBuildString];
This is tested with Xcode Version 4.6.3 (4H1503). The build number is often written in parenthesis / braces. The build number is in hexadecimal or decimal.
这是使用Xcode 版本 4.6.3 (4H1503) 测试的。内部版本号通常写在括号/大括号中。内部版本号为十六进制或十进制。
In Xcodeyou can auto-increment the build numberas a decimal numberby placing the following in the Run script
build phase in the project settings
在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"
For hexadecimalbuild number use this script
对于十六进制版本号,请使用此脚本
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"
回答by iHS
Thanks to @nekno and @ale84 for great answers.
感谢@nekno 和@ale84 提供了很好的答案。
However, I modified @ale84's script it little to increment build numbers for floating point.
但是,我修改了@ale84 的脚本以增加浮点数的内部版本号。
the value of incl can be changed according to your floating format requirements. For eg: if incl = .01, output format would be ... 1.19, 1.20, 1.21 ...
可以根据您的浮动格式要求更改 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"
回答by mark VanderWiele
Another way is to set the version number in appDelegate
didFinishLaunchingWithOptions
:
另一种方法是在 中设置版本号appDelegate
didFinishLaunchingWithOptions
:
- (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];
}