我想在我的应用程序的设置包中包含应用程序版本和内部修订,例如1.0.1(r1243).
Root.plist文件包含这样的片段......
Type PSTitleValueSpecifier Title Version Key version_preference DefaultValue VersionValue Values VersionValue Titles VersionValue
我想在构建时替换"VersionValue"字符串.
我有一个脚本可以从我的存储库中提取版本号,我需要的是一种在构建时处理(预处理)Root.plist文件的方法,并替换版本号而不影响源文件.
还有另一种解决方案比以前的任何一种解决方案都简单得多.Apple 在其大多数安装程序中捆绑了一个名为PlistBuddy的命令行工具,并将其包含在Leopard中/usr/libexec/PlistBuddy
.
由于您要替换VersionValue
,假设您已提取版本值$newVersion
,您可以使用此命令:
/usr/libexec/PlistBuddy -c "Set :VersionValue $newVersion" /path/to/Root.plist
无需使用sed或正则表达式,这种方法非常简单.有关详细说明,请参见手册页.您可以使用PlistBuddy添加,删除或修改属性列表中的任何条目.例如,我的一位朋友发表了关于使用PlistBuddy 在Xcode中增加内部版本号的博文.
注意:如果仅提供plist的路径,PlistBuddy将进入交互模式,因此您可以在决定保存更改之前发出多个命令.我绝对建议在你的构建脚本中填充它之前这样做.
我的懒人的解决方案是从我的应用程序代码更新版本号.你可以在Root.plist中有一个默认(或空白)值,然后在你的启动代码中的某个地方:
NSString *version = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleVersion"]; [[NSUserDefaults standardUserDefaults] setObject:version forKey:@"version_preference"];
唯一的问题是您的应用必须至少运行一次才能使更新版本显示在设置面板中.
您可以进一步理解这个想法,例如,更新您的应用程序启动次数的计数器,或其他有趣的信息.
基于@Quinn的答案,这里是我用来完成此过程的完整过程和工作代码.
将设置包添加到您的应用.不要重命名它.
在文本编辑器中打开Settings.bundle/Root.plist
用以下内容替换内容:
PreferenceSpecifiers Title About Type PSGroupSpecifier DefaultValue DummyVersion Key version_preference Title Version Type PSTitleValueSpecifier StringsTable Root
创建一个Run Script构建阶段,移动到Copy Bundle Resources阶段之后.添加此代码:
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"
将MyAppName替换为您的实际应用程序名称,将PreferenceSpecifiers之后的1替换为Settings中的Version条目的索引.上面的Root.plist示例将它放在索引1处.
使用Ben Clayton的plist /sf/ask/17360801/
之后添加Run script
以下代码段Copy Bundle Resources
.
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
有一些好处.
它不会修改存储库工作副本中的文件.
你不需要到外壳路径Settings.bundle
在$SRCROOT
.路径可能会有所不同.
在Xcode 7.3.1上进行测试
Based on the example here, here's the script I'm using to automatically update the settings bundle version number:
#! /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)
Here's the Root.plist I've got in Settings.bundle:
PreferenceSpecifiers Title About Type PSGroupSpecifier DefaultValue 1.0.0.0 Key version_preference Title Version Type PSTitleValueSpecifier StringsTable Root
由于以下原因,其他答案无法正常工作:在打包设置包之后,才会执行运行脚本构建阶段.因此,如果您的Info.plist版本是2.0.11并且您将其更新为2.0.12,然后构建/存档您的项目,则设置包仍然会说2.0.11.如果打开"设置"包Root.plist,则可以看到版本号在构建过程结束之前不会更新.您可以构建项目AGAIN以正确更新Settings包,或者您可以将脚本添加到预构建阶段而不是......
在XCode中,编辑项目目标的Scheme
单击BUILD方案上的显示箭头
然后,单击"预执行"项
单击加号并选择"新建运行脚本操作"
将shell值设置为/ bin/sh
将"提供构建设置"设置为项目目标
将脚本添加到文本区域.以下脚本适合我.您可能需要修改路径以匹配项目设置:
versionString = $(/ usr/libexec/PlistBuddy -c"Print CFBundleVersion""$ {PROJECT_DIR}/$ {INFOPLIST_FILE}")
/ usr/libexec/PlistBuddy"$ SRCROOT/Settings.bundle/Root.plist"-c"set PreferenceSpecifiers:0:DefaultValue $ versionString"
这将在构建/归档过程中打包设置捆绑包之前正确运行脚本.如果您打开设置包Root.plist并构建/存档项目,您现在将看到版本号在构建过程开始时更新,并且您的设置包将显示正确的版本.