版本与构build在XCode
我有一个使用Xcode 3开发的应用程序,最近开始使用Xcode 4进行编辑。在目标摘要中,我使用了以下字段的iOS应用程序目标表单:标识符,版本,构build,设备和部署目标。 版本字段为空,构build字段为3.4.0(与我使用Xcode 3进行编辑时的应用程序版本相匹配)。
我的问题是:
-
版本和生成字段有什么区别?
-
为什么升级到XCode 4后版本字段为空?
谢谢。
苹果公司重新排列/重新安置了田地。
outlook未来,如果您查看Application Target的Info选项卡,则应该使用“Bundle versions string string,short”作为您的版本(例如3.4.0)和“Bundle version”作为您的Build(例如500或1A500 )。 如果你没有看到他们,你可以添加他们。 这些将映射到“摘要”选项卡上正确的“版本”和“生成”文本框; 他们是相同的价值观。
查看“信息”选项卡时,如果右键单击并select“ 显示原始键/值” ,则会看到实际名称为CFBundleShortVersionString
(Version)和CFBundleVersion
(Build)。
这个版本通常是用来表示你已经在Xcode 3中使用它了。我不确定你在问什么级别的版本/构build差异,所以我会回答它的哲学。
有各种各样的计划,但受欢迎的是:
{MajorVersion}。{MinorVersion}。{}修订
- 主要版本 – 主要更改,重新devise和function更改
- 次要版本 – 小的改进,function的增加
- 修订版 – 修补程序的修补程序号
然后,构build单独使用,以指示版本或整个产品生命周期的构build总数。
许多开发人员在0处启动Build编号,每次构build时都会将编号增加1,永远增加。 在我的项目中,我有一个脚本,每次构build时都会自动增加构build编号。 请参阅下面的说明。
- 版本1.0.0可能构build542.它需要542个版本才能达到1.0.0版本。
- 版本1.0.1可能会build立578。
- 版本1.1.0可能会build立694。
- 版本2.0.0可能会build立949。
包括苹果在内的其他开发人员的内部版本号包含主版本+次版本+版本号。 这些是实际的软件版本号,而不是用于市场营销的值。
如果你去Xcode菜单> 关于Xcode ,你会看到版本号和内部版本号。 如果你点击更多信息…button,你会看到一堆不同的版本。 由于Xcode 5中的“ 更多信息…”button已被删除,因此通过打开Apple菜单>“ 关于本机” >“ 系统报告…” ,也可从系统信息应用程序的软件>开发人员部分获取此信息。
例如,Xcode 4.2(4C139)。 市场版本4.2是build立主要版本4,build立次要版本C和build立编号139.下一个版本(推测4.3)可能是生成版本4D,并且build立编号将从0开始并且从那里增量。
iPhone模拟器版本/内部版本号与iPhone,Mac等一样。
- 3.2:(7W367a)
- 4.0:(8A400)
- 4.1:(8B117)
- 4.2:(8C134)
- 4.3:(8H7)
更新 :通过请求,下面是创build一个脚本的步骤,每次在Xcode中构build应用程序时都会运行脚本来读取Build号码,将其增加,然后将其写回到应用程序的{App}-Info.plist
文件中。 如果要将版本/内部版本号写入Settings.bundle/Root*.plist
文件,则还有可选的附加步骤。
这是从这篇how-to文章扩展而来的。
在Xcode 4.2 – 5.0中:
- 加载你的Xcode项目。
- 在左侧窗格中,单击层次结构顶部的项目。 这将加载项目设置编辑器。
- 在中心窗格的左侧,点击TARGETS标题下的应用程序。 您将需要为每个项目目标configuration此设置。
- select“ 构build阶段”选项卡。
-
- 在Xcode 4的右下angular,点击Add Build Phasebutton并selectAdd Run Script 。
- 在Xcode 5中,select编辑器菜单> 添加生成阶段 > 添加运行脚本生成阶段 。
- 拖放新的“运行脚本”阶段,将其移动到“ 复制包资源”阶段之前(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指出的那样, 苹果通用版本工具 (
agvtool
)也是可用的。 如果你喜欢使用它,那么有几件事情需要改变:- select生成设置选项卡。
- 在“ 版本控制”部分下,将“ 当前项目版本”设置为要使用的初始版本号,例如1 。
- 返回到“ 构build阶段”选项卡上,在“ 复制包资源 ”阶段之后拖放“运行脚本”阶段,以避免在尝试构build和更新包含构build编号的源文件时出现争用情况。
请注意,使用
agvtool
方法,您可能仍会定期获取失败/已取消的构build,而且没有任何错误。 出于这个原因,我不build议在这个脚本中使用agvtool
。不过,在“运行脚本”阶段,您可以使用以下脚本:
"${DEVELOPER_BIN_DIR}/agvtool" next-version -all
next-version
参数会增加next-version
号(bump
也是同一个事件的别名),并且会使用新的版本号更新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
(只是把它留在这里供我自己参考。)这将显示在Xcode目标中看到的“version”和“build”字段的版本和构build:
- (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)" }
内部编号是一个内部编号,表示应用程序的当前状态。 它不同于版本号,因为它通常不是面向用户的,并且不象版本号通常那样表示任何差异/特征/升级。
像这样想:
- 构build(
CFBundleVersion
):构build的数量。 通常你从1开始,每增加一个应用程序就增加1。 它可以快速地比较哪个版本更新,它代表了代码库的进度感。 在使用QA进行工作时,这些可能是非常有价值的,并且需要确保在正确的构build中logging错误。 - 营销版本(
CFBundleShortVersionString
):用于表示您的应用的此版本的用户正在使用的号码。 通常这遵循Major.minor版本计划(例如MyAwesomeApp 1.2),以便让用户知道哪些发行版是较小的维护更新,哪些是很大的新function。
为了在您的项目中有效地使用它,Apple提供了一个称为agvtool
的强大工具。 我强烈build议使用这个,因为它比脚本更改更简单。 它使您可以轻松设置内部版本号和市场营销版本。 在编写脚本时(例如,轻松更新每个版本的内部版本号,甚至查询当前内部版本号是什么),该function特别有用。 它甚至可以做更多的奇特的事情,如更新内部版本号时为您添加SVN标签。
要使用它:
- 在版本控制下的Xcode中将项目设置为使用“Apple Generic”。
- 在terminal
-
agvtool new-version 1
(将agvtool new-version 1
设置为1) -
agvtool new-marketing-version 1.0
(设置营销版本为1.0)
-
查看agvtool
的手册页获取大量信息
在上面的答案中自动增加内部版本号的脚本不适用于我,如果内部版本号是一个浮点值,所以我修改了一下:
#!/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 。 这个数字是关于发布和新function的。
内部 版本号大部分是在此之前制作的内部版本号 。 但有些使用其他数字,如存储库的分支号码。 这个数字应该是唯一的,以区分几乎相同的构build。
正如你所看到的,内部版本号是没有必要的,它取决于你想要使用的内部版本号 。 所以,如果你更新你的Xcode
到一个主版本,生成字段是空的。 版本字段可能不是空的!
将内部版本号作为NSString
variables获取:
NSString * appBuildString = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleVersion"];
要将版本号作为NSString
variables:
NSString * appVersionString = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleShortVersionString"];
如果你想同时在一个NSString
:
NSString * versionBuildString = [NSString stringWithFormat:@"Version: %@ (%@)", appVersionString, appBuildString];
这是用Xcode版本4.6.3(4H1503)进行testing。 内部版本号通常写在括号/大括号中。 内部版本号是hex或十进制。
在Xcode中,您可以通过在项目设置的Run script
构build阶段中放置以下内容来自动递增内部版本号作为十进制数字
#!/bin/bash buildNumber=$(/usr/libexec/PlistBuddy -c "Print CFBundleVersion" "$INFOPLIST_FILE") buildNumber=$(($buildNumber + 1)) /usr/libexec/PlistBuddy -c "Set :CFBundleVersion $buildNumber" "$INFOPLIST_FILE"
对于hex内部版本号使用这个脚本
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"
另一种方法是在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]; }