如何在应用程序的设置包中显示应用程序版本修订版?

我想在应用程序的设置包中包含应用程序版本和内部版本,如1.0.1(r1243)。

Root.plist文件包含这样一个片段…

<dict> <key>Type</key> <string>PSTitleValueSpecifier</string> <key>Title</key> <string>Version</string> <key>Key</key> <string>version_preference</string> <key>DefaultValue</key> <string>VersionValue</string> <key>Values</key> <array> <string>VersionValue</string> </array> <key>Titles</key> <array> <string>VersionValue</string> </array> </dict> 

我想在构build时replace“VersionValue”string。

我有一个脚本,可以从我的存储库中提取版本号,我需要的是一种在构build时处理(预处理)Root.plist文件的方法,并在不影响源文件的情况下replace版本号。

还有另一个解决scheme可以比以前的答案简单得多。 苹果在大多数安装程序中捆绑了名为PlistBuddy的命令行工具,并将其包含在Leopard的/usr/libexec/PlistBuddy

由于您想要replaceVersionValue ,因此假设您已将版本值提取到$newVersion ,则可以使用以下命令:

 /usr/libexec/PlistBuddy -c "Set :VersionValue $newVersion" /path/to/Root.plist 

不需要使用sed或正则expression式,这种方法非常简单。 有关详细说明,请参阅手册页 。 您可以使用PlistBuddy添加,删除或修改属性列表中的任何条目。 例如,我的一个朋友在使用PlistBuddy 在Xcode中增加了内部版本号 。

注意:如果您只提供plist的path,PlistBuddy将进入交互模式,因此您可以在决定保存更改之前发出多个命令。 我绝对推荐你在构build脚本之前先做这个。

我的懒人的解决scheme是从我的应用程序代码更新版本号。 您可以在Root.plist中有一个默认(或空白)值,然后在启动代码中的某处:

 NSString *version = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleVersion"]; [[NSUserDefaults standardUserDefaults] setObject:version forKey:@"version_preference"]; 

唯一的问题是您的应用程序必须至less运行一次才能使更新后的版本显示在设置面板中。

您可以进一步理解并更新,例如,您的应用程序启动了多less次,或者其他有趣的信息。

基于@ Quinn的回答,这里是我用来完成这个过程的全部过程和工作代码。

  • 添加一个设置包到您的应用程序。 不要重命名它。
  • 在文本编辑器中打开Settings.bundle / Root.plist

将内容replace为:

 <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict> <key>PreferenceSpecifiers</key> <array> <dict> <key>Title</key> <string>About</string> <key>Type</key> <string>PSGroupSpecifier</string> </dict> <dict> <key>DefaultValue</key> <string>DummyVersion</string> <key>Key</key> <string>version_preference</string> <key>Title</key> <string>Version</string> <key>Type</key> <string>PSTitleValueSpecifier</string> </dict> </array> <key>StringsTable</key> <string>Root</string> </dict> </plist> 
  • 创build一个运行脚本构build阶段,移动到复制包资源阶段之后。 添加以下代码:

     cd "${BUILT_PRODUCTS_DIR}" buildVersion=$(/usr/libexec/PlistBuddy -c "Print CFBundleVersion" "${INFOPLIST_PATH}" ) /usr/libexec/PlistBuddy -c "Set PreferenceSpecifiers:1:DefaultValue $buildVersion" "${WRAPPER_NAME}/Settings.bundle/Root.plist" 
  • 将MyAppNamereplace为您的实际应用程序的名称,PreferenceSpecifiers之后的1将成为“设置”中“版本”条目的索引。 上面的Root.plist例子在索引1处有。

基于这里的例子,下面是我用来自动更新设置包版本号的脚本:

 #! /usr/bin/env python import os from AppKit import NSMutableDictionary settings_file_path = 'Settings.bundle/Root.plist' # the relative path from the project folder to your settings bundle settings_key = 'version_preference' # the key of your settings version # these are used for testing only info_path = '/Users/mrwalker/developer/My_App/Info.plist' settings_path = '/Users/mrwalker/developer/My_App/Settings.bundle/Root.plist' # these environment variables are set in the XCode build phase if 'PRODUCT_SETTINGS_PATH' in os.environ.keys(): info_path = os.environ.get('PRODUCT_SETTINGS_PATH') if 'PROJECT_DIR' in os.environ.keys(): settings_path = os.path.join(os.environ.get('PROJECT_DIR'), settings_file_path) # reading info.plist file project_plist = NSMutableDictionary.dictionaryWithContentsOfFile_(info_path) project_bundle_version = project_plist['CFBundleVersion'] # print 'project_bundle_version: '+project_bundle_version # reading settings plist settings_plist = NSMutableDictionary.dictionaryWithContentsOfFile_(settings_path) for dictionary in settings_plist['PreferenceSpecifiers']: if 'Key' in dictionary and dictionary['Key'] == settings_key: dictionary['DefaultValue'] = project_bundle_version # print repr(settings_plist) settings_plist.writeToFile_atomically_(settings_path, True) 

这是我在Settings.bundle中获得的Root.plist:

 <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict> <key>PreferenceSpecifiers</key> <array> <dict> <key>Title</key> <string>About</string> <key>Type</key> <string>PSGroupSpecifier</string> </dict> <dict> <key>DefaultValue</key> <string>1.0.0.0</string> <key>Key</key> <string>version_preference</string> <key>Title</key> <string>Version</string> <key>Type</key> <string>PSTitleValueSpecifier</string> </dict> </array> <key>StringsTable</key> <string>Root</string> </dict> </plist> 

我设法通过使用pListcompiler( http://sourceforge.net/projects/plistcompiler )开源项目来做我想做的事情。

  1. 使用此编译器,您可以使用以下格式将属性文件写入.plc文件中:

     plist { dictionary { key "StringsTable" value string "Root" key "PreferenceSpecifiers" value array [ dictionary { key "Type" value string "PSGroupSpecifier" key "Title" value string "AboutSection" } dictionary { key "Type" value string "PSTitleValueSpecifier" key "Title" value string "Version" key "Key" value string "version" key "DefaultValue" value string "VersionValue" key "Values" value array [ string "VersionValue" ] key "Titles" value array [ string "r" kRevisionNumber ] } ] } } 
  2. 我有一个自定义的运行脚本构build阶段,它将brad-larson所描述的我的存储库版本解压缩为.h文件。

  3. plc文件可以包含预处理指令,如#define,#message,#if,#elif,#include,#warning,#ifdef,#else,#pragma,#error,#ifndef,#endif,xcode环境variables。 所以我可以通过添加下面的指令来引用variableskRevisionNumber

     #include "Revision.h" 
  4. 我还为我的xcode目标添加了一个自定义脚本构build阶段,以在每次构build项目时运行编译器

     /usr/local/plistcompiler0.6/plcompile -dest Settings.bundle -o Root.plist Settings.plc 

这就是它!

使用本克莱顿的plist https://stackoverflow.com/a/12842530/338986

Copy Bundle Resources后添加Run script与以下片段。

 version=$(/usr/libexec/PlistBuddy -c "Print CFBundleShortVersionString" "$PROJECT_DIR/$INFOPLIST_FILE") build=$(/usr/libexec/PlistBuddy -c "Print CFBundleVersion" "$PROJECT_DIR/$INFOPLIST_FILE") /usr/libexec/PlistBuddy -c "Set PreferenceSpecifiers:1:DefaultValue $version ($build)" "$CODESIGNING_FOLDER_PATH/Settings.bundle/Root.plist" 

附加CFBundleVersion附加CFBundleShortVersionString 。 它发出这样的版本:

通过写入$CODESIGNING_FOLDER_PATH/Settings.bundle/Root.plist而不是$SRCROOT中的一个,有一些好处。

  1. 它不会修改存储库工作副本中的文件。
  2. 您不需要在$SRCROOT指定Settings.bundlepath。 path可能会有所不同。

在Xcode 7.3.1上testing

其他的答案不能正常工作的原因之一:运行脚本的构build阶段不会执行,直到设置包已被打包。 所以,如果你的Info.plist版本是2.0.11,你更新到2.0.12,然后build立/存档你的项目,设置包仍然会说2.0.11。 如果打开设置包Root.plist,则可以看到版本号在构build过程结束之前不会更新。 您可以再次构build项目,以正确更新设置包,或者您可以将脚本添加到预生成阶段,而不是…

  • 在XCode中,编辑项目目标的Scheme
  • 点击BUILDscheme上的显示箭头
  • 然后,点击“预执行”项目
  • 点击加号并select“New Run Script Action”
  • 将shell值设置为/ bin / sh
  • 将“提供构build设置”设置为您的项目目标
  • 将您的脚本添加到文本区域。 以下脚本为我工作。 您可能需要修改path以匹配您的项目设置:

    versionString = $(/ usr / libexec / PlistBuddy -c“打印CFBundleVersion”“$ {PROJECT_DIR} / $ {INFOPLIST_FILE}”)

    / usr / libexec / PlistBuddy“$ SRCROOT / Settings.bundle / Root.plist”-c“PreferenceSpecifiers:0:DefaultValue $ versionString”

这将在构build/归档过程中打包设置包之前正确运行脚本。 如果您打开Settings捆绑包Root.plist并构build/存档您的项目,现在您将看到版本号在构build过程开始时被更新,您的Settings捆绑包将显示正确的版本。

我相信你可以使用一种类似于我在这个答案中描述的方式来做到这一点 (基于这个职位 )。

首先,您可以将XVa中的VersionValuevariables重命名为$ {VERSIONVALUE}。 创build一个名为versionvalue.xcconfig的文件并将其添加到您的项目中。 转到您的应用程序目标并转到该目标的“生成”设置。 我相信你需要添加VERSIONVALUE作为用户定义的构build设置。 在该窗口的右下angular,将“基于”值更改为“版本值”。

最后,转到目标并创build运行脚本构build阶段。 检查“运行脚本”阶段,并在脚本文本字段中粘贴脚本。 例如,我的脚本将BUILD_NUMBER设置标记为当前的Subversion版本,如下所示:

 REV=`/usr/bin/svnversion -nc ${PROJECT_DIR} | /usr/bin/sed -e 's/^[^:]*://;s/[A-Za-z]//'` echo "BUILD_NUMBER = $REV" > ${PROJECT_DIR}/buildnumber.xcconfig 

当这些值在你的项目中改变时,这应该做一个replacevariables的技巧。