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

Pan*_*ros 83 iphone xcode application-settings settings-bundle

我想在我的应用程序的设置包中包含应用程序版本和内部修订,例如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>
Run Code Online (Sandbox Code Playgroud)

我想在构建时替换"VersionValue"字符串.

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

Qui*_*lor 68

还有另一种解决方案比以前的任何一种解决方案都简单得多.Apple 在其大多数安装程序中捆绑了一个名为PlistBuddy的命令行工具,并将其包含在Leopard中/usr/libexec/PlistBuddy.

由于您要替换VersionValue,假设您已提取版本值$newVersion,您可以使用此命令:

/usr/libexec/PlistBuddy -c "Set :VersionValue $newVersion" /path/to/Root.plist
Run Code Online (Sandbox Code Playgroud)

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

注意:如果仅提供plist的路径,PlistBuddy将进入交互模式,因此您可以在决定保存更改之前发出多个命令.我绝对建议在你的构建脚本中填充它之前这样做.

  • 我找了一段时间来找出正确的方法来引用我的plist中的版本号; 在我的情况下,它原来是/ usr/libexec/PlistBuddy Settings.bundle/Root.plist -c"set PreferenceSpecifiers:0:DefaultValue $ newversion" - 希望这对其他人有用. (20认同)
  • 从自定义的"运行脚本"构建阶段,我需要包含更多的Root.plist路径:/ usr/libexec/PlistBuddy $ {TARGET_BUILD_DIR}/$ {FULL_PRODUCT_NAME} /Settings.bundle/Root.plist -c"set PreferenceSpecifiers:0:DefaultValue $ newVersion" (7认同)
  • 为了完整起见,这是PListBuddy为我工作的另一种方法:http://xcodehelp.blogspot.com/2012/05/add-version-number-to-settings-screen.html (2认同)

小智 65

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

NSString *version = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleVersion"];
[[NSUserDefaults standardUserDefaults] setObject:version forKey:@"version_preference"];
Run Code Online (Sandbox Code Playgroud)

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

您可以进一步理解这个想法,例如,更新您的应用程序启动次数的计数器,或其他有趣的信息.

  • @Moshe True,但为了优雅地处理这个问题,你可以简单地在.plist文件中指定一个默认值,也许就像'Not Yet Launched' (9认同)
  • 这将起作用,除非用户在启动您的应用之前进入设置*. (8认同)
  • 我错过了什么吗?这正是我正在做的事情,但价值不会改变.你们有没有使用Title属性,我认为这是只读的? (3认同)
  • 更新应用程序时还有另一个问题.在更新的应用程序至少启动一次之前,设置包仍将显示旧的构建版本. (2认同)

Ben*_*ton 59

基于@Quinn的答案,这里是我用来完成此过程的完整过程和工作代码.

  • 将设置包添加到您的应用.不要重命名它.
  • 在文本编辑器中打开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>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>
Run Code Online (Sandbox Code Playgroud)
  • 创建一个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"
    
    Run Code Online (Sandbox Code Playgroud)
  • 将MyAppName替换为您的实际应用程序名称,将PreferenceSpecifiers之后的1替换为Settings中的Version条目的索引.上面的Root.plist示例将它放在索引1处.

  • bash脚本@ ben-clayton put对我不起作用,所以我根据他的回答重新制作它,这里是:`buildVersion = $(/ usr/libexec/PlistBuddy -c"Print CFBundleShortVersionString""$ {PROJECT_DIR}/$ {INFOPLIST_FILE}")``/ usr/libexec/PlistBuddy -c"设置PreferenceSpecifiers:3:DefaultValue $ buildVersion""$ {SRCROOT} /Settings.bundle/Root.plist"` (8认同)

hir*_*shi 20

使用Ben Clayton的plist /sf/answers/898977131/

之后添加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"
Run Code Online (Sandbox Code Playgroud)

附加CFBundleVersion附加CFBundleShortVersionString.它发出如下版本:

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

  1. 它不会修改存储库工作副本中的文件.
  2. 你不需要到外壳路径Settings.bundle$SRCROOT.路径可能会有所不同.

在Xcode 7.3.1上进行测试

  • 这对我有用。只需记住将“DefaultValue”更改为特定于您的值即可。例如,我想更改页脚,所以我使用“FooterText”。您还需要更改“PreferenceSpecifiers”后面的数字,以便它与 plist 中的项目相关联。 (2认同)

mrw*_*ker 12

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)
Run Code Online (Sandbox Code Playgroud)

Here's the Root.plist I've got in Settings.bundle:

<?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>
Run Code Online (Sandbox Code Playgroud)


Ima*_*tit 11

使用 Xcode 11.4,您可以使用以下步骤在应用程序的设置包中显示应用程序版本。


集合$(MARKETING_VERSION)$(CURRENT_PROJECT_VERSION)变量

注意:如果Info.plist 中出现了$(MARKETING_VERSION)and$(CURRENT_PROJECT_VERSION)变量Bundle version string (short)Bundle version键 ,可以跳过以下步骤直接跳转到下一节。

  1. 打开 Xcode 项目。
  2. 打开项目导航器( cmd1),选择您的项目以显示您的项目设置,然后选择应用程序目标。
  3. 选择常规选项卡。
  4. Identity部分,将Version字段内容更改为某个新值(例如0.1.0)并将Build字段内容更改为某个新值(例如12)。这 2 个更改将在Info.plist文件中创建$(MARKETING_VERSION)$(CURRENT_PROJECT_VERSION)变量。

创建和配置设置包

  1. Project Navigator 中,选择您的项目。
  2. 选择文件>新建>文件... ( cmdN)。
  3. 选择iOS选项卡。
  4. Resource部分中选择Settings Bundle,然后单击NextCreate
  5. 选择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>DefaultValue</key>
            <string></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>
Run Code Online (Sandbox Code Playgroud)

添加运行脚本

  1. Project Navigator 中,选择您的项目。
  2. 选择应用目标。
  3. 选择构建阶段选项卡。
  4. 单击+ >新建运行脚本阶段
  5. 将新阶段拖放到Copy Bundle Resources部分上方的某个位置。这样,脚本将在编译应用程序之前执行。
  6. 打开新添加的运行脚本阶段并添加以下脚本:
version="$MARKETING_VERSION"
build="$CURRENT_PROJECT_VERSION"
/usr/libexec/PlistBuddy -c "Set PreferenceSpecifiers:0:DefaultValue $version ($build)" "${SRCROOT}/Settings.bundle/Root.plist"
Run Code Online (Sandbox Code Playgroud)

启动应用

  1. cmdR在设备或模拟器上运行产品 ( )。
  2. 在设备或模拟器上,启动应用程序后,打开设置应用程序并在第三方应用程序列表中选择您的应用程序。该应用程序的版本应显示如下:


来源

  • 这对我有用: `/usr/libexec/PlistBuddy "$SRCROOT/AppName/Settings.bundle/Root.plist" -c "set PreferenceSpecifiers:0:DefaultValue $version"` (3认同)
  • 这对我来说直接有效,谢谢!最好一步一步回答!! (2认同)

小智 8

由于以下原因,其他答案无法正常工作:在打包设置包之后,才会执行运行脚本构建阶段.因此,如果您的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并构建/存档项目,您现在将看到版本号在构建过程开始时更新,并且您的设置包将显示正确的版本.


Pan*_*ros 3

我设法通过使用 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
                    ]
                }
            ]
        }
    }
    
    Run Code Online (Sandbox Code Playgroud)
  2. 我有一个自定义运行脚本构建阶段,它将我的存储库修订版本提取到 .h 文件,如 Brad-larson此处所述。

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

    #include "Revision.h"
    
    Run Code Online (Sandbox Code Playgroud)
  4. 我还在我的 xcode 目标中添加了一个自定义脚本构建阶段,以便在每次项目构建时运行 plcompiler

    /usr/local/plistcompiler0.6/plcompile -dest Settings.bundle -o Root.plist Settings.plc
    
    Run Code Online (Sandbox Code Playgroud)

就是这样!