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

发布于 2024-07-20 23:24:49 字数 899 浏览 8 评论 0 原文

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

我想在构建时替换“VersionValue”字符串。

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

I would like to include the application version and internal revision, something like 1.0.1 (r1243), in my application's settings bundle.

The Root.plist file contains a fragment like this...

     <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>

and I would like to replace the "VersionValue" string at build time.

I have a script that can extract the version number from my repository, what I need is a way to process (pre-process) the Root.plist file, at build time, and replace the revision number without affecting the source file.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(13

狼性发作 2024-07-27 23:24:49

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

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

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

无需摆弄 sed 或正则表达式,这种方法非常简单。 有关详细说明,请参阅手册页。 您可以使用 PlistBuddy 添加、删除或修改属性列表中的任何条目。 例如,我的一个朋友在博客中介绍了在 Xcode 中递增内部版本号< /a> 使用 PlistBuddy。

注意:如果您仅提供 plist 的路径,PlistBuddy 会进入交互模式,因此您可以在决定保存更改之前发出多个命令。 我绝对建议在将其放入构建脚本之前执行此操作。

There is another solution that can be much simpler than either of the previous answers. Apple bundles a command-line tool called PlistBuddy inside most of its installers, and has included it in Leopard at /usr/libexec/PlistBuddy.

Since you want to replace VersionValue, assuming you have the version value extracted into $newVersion, you could use this command:

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

No need to fiddle with sed or regular expressions, this approach is quite straightforward. See the man page for detailed instructions. You can use PlistBuddy to add, remove, or modify any entry in a property list. For example, a friend of mine blogged about incrementing build numbers in Xcode using PlistBuddy.

Note: If you supply just the path to the plist, PlistBuddy enters interactive mode, so you can issue multiple commands before deciding to save changes. I definitely recommend doing this before plopping it in your build script.

[浮城] 2024-07-27 23:24:49

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

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

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

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

My lazy man's solution was to update the version number from my application code. You could have a default (or blank) value in the Root.plist and then, somewhere in your startup code:

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

The only catch is that your app would have to be run at least once for the updated version to appear in the settings panel.

You could take the idea further and update, for instance, a counter of how many times your app has been launched, or other interesting bits of information.

何时共饮酒 2024-07-27 23:24:49

根据@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>
  • 创建一个运行脚本构建阶段,移至复制捆绑资源阶段之后。 添加此代码:

    cd "${BUILT_PRODUCTS_DIR}" 
      buildVersion=$(/usr/libexec/PlistBuddy -c "打印 CFBundleVersion" "${INFOPLIST_PATH}" ) 
      /usr/libexec/PlistBuddy -c“设置 PreferenceSpecifiers:1:DefaultValue $buildVersion”“${WRAPPER_NAME}/Settings.bundle/Root.plist” 
      
  • 将 MyAppName 替换为您的实际应用程序名称,并将 PreferenceSpecifiers 后面的 1 替换为“设置”中版本条目的索引。 上面的 Root.plist 示例的索引为 1。

Based on @Quinn's answer, here the full process and working code I use to do this.

  • Add a settings bundle to your app. Don't rename it.
  • Open Settings.bundle/Root.plist in a text editor

Replace the contents with:

<?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>
  • Create a Run Script build phase, move to be after the Copy Bundle Resources phase. Add this code:

    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"
    
  • Replace MyAppName with your actual app's name, and the 1 after PreferenceSpecifiers to be the index of your Version entry in the Settings. The above Root.plist example has it at index 1.

黄昏下泛黄的笔记 2024-07-27 23:24:49

使用 Ben Clayton 的 plist https://stackoverflow.com/a/12842530/338986

添加 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"

除了 CFBundleShortVersionString 之外,还附加 CFBundleVersion
它发出这样的版本:

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

  1. 它不会修改存储库工作副本中的文件。
  2. 您无需在 $SRCROOT 中设置 Settings.bundle 的路径。 路径可能会有所不同。

在 Xcode 7.3.1 上测试

Using Ben Clayton's plist https://stackoverflow.com/a/12842530/338986

Add Run script with following snippet after 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"

Appending CFBundleVersion in addition of CFBundleShortVersionString.
It emit version like this:

By writing to
$CODESIGNING_FOLDER_PATH/Settings.bundle/Root.plist
instead of the one in $SRCROOT have some benefits.

  1. It dosen't modify files in working copy of repository.
  2. You don't need to case path to Settings.bundle in $SRCROOT. The path may vary.

Testing on Xcode 7.3.1

零崎曲识 2024-07-27 23:24:49

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


设置 $(MARKETING_VERSION)$(CURRENT_PROJECT_VERSION) 变量

注意:如果 $(MARKETING_VERSION)$(CURRENT_PROJECT_VERSION) > Info.plist 中的 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. 项目导航器中,选择您的项目。
  2. 选择文件> > 文件... (cmdN)。
  3. 选择iOS选项卡。
  4. 资源部分中选择设置包,然后单击下一步创建
  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>

添加运行脚本

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

启动应用程序

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


来源

With Xcode 11.4, you can use the following steps to display the app version in your application's settings bundle.


Set $(MARKETING_VERSION) and $(CURRENT_PROJECT_VERSION) variables

Note: if $(MARKETING_VERSION) and $(CURRENT_PROJECT_VERSION) variables appear for Bundle version string (short) and Bundle version keys in Info.plist, you can skip the following steps and jump to the next section.

  1. Open the Xcode project.
  2. Open Project Navigator (cmd1), select your project to reveal your project's settings then select the app target.
  3. Select the General tab.
  4. In the Identity section, change the Version field content to some new value (e.g. 0.1.0) and change the Build field content to some new value (e.g. 12). These 2 changes will create $(MARKETING_VERSION) and $(CURRENT_PROJECT_VERSION) variables in Info.plist file.

Create and configure Settings Bundle

  1. In the Project Navigator, select your project.
  2. Select File > New > File… (cmdN).
  3. Select the iOS tab.
  4. Select Settings Bundle in the Resource section, then click Next and Create.
  5. Select Root.plist and open it as source code. Replace its content with the code below:
<?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>

Add a Run Script

  1. In the Project Navigator, select your project.
  2. Select the app target.
  3. Select the Build Phases tab.
  4. Click + > New Run Script Phase.
  5. Drag and drop the new phase somewhere above Copy Bundle Resources section. In this way, the script will be executed before compiling the application.
  6. Open the newly added Run Script phase and add the following script:
version="$MARKETING_VERSION"
build="$CURRENT_PROJECT_VERSION"
/usr/libexec/PlistBuddy -c "Set PreferenceSpecifiers:0:DefaultValue $version ($build)" "${SRCROOT}/Settings.bundle/Root.plist"

Launch app

  1. Run the product (cmdR) on device or simulator.
  2. On the device or simulator, once the app is launched, open Settings app and select your app in the list of third-party apps. The app's version should be displayed as shown below:


Sources

沐歌 2024-07-27 23:24:49

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

#! /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>

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:

<?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>
蓝颜夕 2024-07-27 23:24:49

由于一个原因,其他答案无法正常工作:
在打包设置包之后,才会执行运行脚本构建阶段。 因此,如果您的 Info.plist 版本是 2.0.11 并且您将其更新到 2.0.12,然后构建/归档您的项目,Settings 包仍会显示 2.0.11。 如果打开 Settings 包 Root.plist,您可以看到版本号直到构建过程结束才更新。 您可以再次构建项目以正确更新设置包,或者您可以将脚本添加到预构建阶段...

  • 在 XCode 中,编辑项目目标的方案
  • 单击构建方案上的公开箭头
  • 然后,单击“Pre-actions”项
  • 单击加号并选择“New Run Script Action”
  • 将 shell 值设置为 /bin/sh
  • 将“Provide build settings from”设置为项目目标
  • 将脚本添加到文本区域。 以下脚本对我有用。 您可能需要修改路径以匹配您的项目设置:

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

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

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

The other answers do not work correctly for one reason:
The run script build phase isn't executed until AFTER the Settings Bundle has been packaged. So, if your Info.plist version is 2.0.11 and you update it to 2.0.12, then build/archive your project, the Settings bundle will still say 2.0.11. If you open the Settings bundle Root.plist, you can see that the version number does not get updated until the END of the build process. You can build the project AGAIN to get the Settings bundle updated correctly, or you can add the script to a pre-build phase instead...

  • In XCode, Edit the Scheme for your project target
  • Click the disclosure arrow on the BUILD scheme
  • Then, click on the "Pre-actions" item
  • Click the plus sign and choose "New Run Script Action"
  • Set the shell value to /bin/sh
  • Set "Provide build settings from" to your project target
  • Add your script to the text area. The following script worked for me. You may need to modify the paths to match your project setup:

    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"

This will correctly run the script BEFORE the Settings bundle is packaged during the build/archive process. If you open the Settings bundle Root.plist and build/archive your project, you will now see the version number is updated at the beginning of the build process and your Settings bundle will display the correct version.

留蓝 2024-07-27 23:24:49

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

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

    <前><代码>plist {
    字典{
    键“StringsTable”值字符串“Root”
    键“P​​referenceSpecifiers”值数组[
    字典{
    键“类型”值字符串“PSGroupSpecifier”
    键“标题”值字符串“AboutSection”
    }
    字典{
    键“类型”值字符串“PSTitleValueSpecifier”
    键“标题”值字符串“版本”
    键“键”值字符串“版本”
    键“DefaultValue”值字符串“VersionValue”
    键“值”值数组[
    字符串“版本值”
    ]
    键“标题”值数组 [
    字符串“r”kRevisionNumber
    ]
    }
    ]
    }
    }

  2. 我有一个自定义运行脚本构建阶段,该阶段将我的存储库修订版本提取到 .h 文件,如下所述作者:brad-larson 这里

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

    <前><代码>#include“Revision.h”

  4. 我还在我的 xcode 目标中添加了一个自定义脚本构建阶段,以便在每次构建项目时运行 plcompiler

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

就是这样!

I managed to do what I wanted by using the pListcompiler (http://sourceforge.net/projects/plistcompiler) open source porject.

  1. Using this compiler you can write the property file in a .plc file using the following format:

    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. I had a custom run script build phase that was extracting my repository revision to .h file as described by brad-larson here.

  3. The plc file can contain preprocessor directives, like #define, #message, #if, #elif, #include, #warning, #ifdef, #else, #pragma, #error, #ifndef, #endif, xcode environment variables. So I was able to reference the variable kRevisionNumber by adding the following directive

    #include "Revision.h"
    
  4. I also added a custom script build phase to my xcode target to run the plcompiler every time the project is beeing build

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

And that was it!

旧时光的容颜 2024-07-27 23:24:49

我的工作示例基于@Ben Clayton 的回答以及@Luis Ascorbe 和@Vahid Amiri 的评论:

注意:此方法会修改存储库工作副本中的Settings.bundle/Root.plist文件

  1. 将设置包添加到项目根目录。 不要重命名

  2. Open Settings.bundle/Root.plist as SourceCode

    将内容替换为:

     
       
       
      <字典> 
          首选项说明符 
          <数组> 
              <字典> 
                  <键>默认值 
                  <字符串> 
                  <键>键 
                  <字符串>version_preference 
                  <键>标题 
                  <字符串>版本 
                  <键>类型 
                  <字符串>PSTitleValueSpecifier 
               
           
          StringsTable 
          <字符串>根 
       
       
      
  3. 将以下脚本添加到项目(目标)方案的 Build、Pre-actions 部分

    version=$(/usr/libexec/PlistBuddy -c“打印 CFBundleShortVersionString”“$PROJECT_DIR/$INFOPLIST_FILE”) 
      build=$(/usr/libexec/PlistBuddy -c“打印 CFBundleVersion”“$PROJECT_DIR/$INFOPLIST_FILE”) 
    
      /usr/libexec/PlistBuddy -c“设置 PreferenceSpecifiers:0:DefaultValue $version ($build)”“${SRCROOT}/Settings.bundle/Root.plist” 
      
  4. 构建并运行当前方案

My working Example based on @Ben Clayton answer and the comments of @Luis Ascorbe and @Vahid Amiri:

Note: This approach modifies the Settings.bundle/Root.plist file in working copy of repository

  1. Add a settings bundle to your project root. Don't rename it

  2. Open Settings.bundle/Root.plist as SourceCode

    Replace the contents with:

    <?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>
    
  3. Add the following script to the Build, Pre-actions section of the project (target) scheme

    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:0:DefaultValue $version ($build)" "${SRCROOT}/Settings.bundle/Root.plist"
    
  4. Build and Run the current scheme

清欢 2024-07-27 23:24:49

以上答案对我不起作用,因此我创建了自定义脚本。

这会动态更新 Root.plist 中的条目

使用下面的运行脚本。 瓦
在 Xcode 10.3 中确实可以正常工作。

“var buildVersion”是标题中显示的版本。

对于 settings.bundle Root.plist 中的标题,标识符名称为“var version” 下面

cd "${BUILT_PRODUCTS_DIR}"

#set version name to your title identifier's string from settings.bundle
var version = "Version"

#this will be the text displayed in title
longVersion=$(/usr/libexec/PlistBuddy -c "Print CFBundleVersion" "${INFOPLIST_PATH}")
shortVersion=$(/usr/libexec/PlistBuddy -c "Print :CFBundleShortVersionString" ${TARGET_BUILD_DIR}/${INFOPLIST_PATH})
buildVersion="$shortVersion.$longVersion"

path="${WRAPPER_NAME}/Settings.bundle/Root.plist"

settingsCnt=`/usr/libexec/PlistBuddy -c "Print PreferenceSpecifiers:" ${path} | grep "Dict"|wc -l`

for (( idx=0; idx<$settingsCnt; idx++ ))
do
#echo "Welcome $idx times"
val=`/usr/libexec/PlistBuddy -c "Print PreferenceSpecifiers:${idx}:Key" ${path}`
#echo $val

#if ( "$val" == "Version" )
if [ $val == "Version" ]
then
#echo "the index of the entry whose 'Key' is 'version' is $idx."

# now set it
/usr/libexec/PlistBuddy -c "Set PreferenceSpecifiers:${idx}:DefaultValue $buildVersion" $path

# just to be sure that it worked
ver=`/usr/libexec/PlistBuddy -c "Print PreferenceSpecifiers:${idx}:DefaultValue" $path`
#echo 'PreferenceSpecifiers:$idx:DefaultValue set to: ' $ver

fi

done

Root.plist 中的示例条目

    <dict>
        <key>Type</key>
        <string>PSTitleValueSpecifier</string>
        <key>Title</key>
        <string>Version</string>
        <key>DefaultValue</key>
        <string>We Rock</string>
        <key>Key</key>
        <string>Version</string>
    </dict>

工作示例 Root.plist 条目

Above answers did not work for me hence I created my custom script.

This dynamically updates the entry from Root.plist

Use run script below. W
ill work for sure verified in xcode 10.3.

"var buildVersion" is the version to be displayed in title.

And identifier name is "var version" below for title in settings.bundle Root.plist

cd "${BUILT_PRODUCTS_DIR}"

#set version name to your title identifier's string from settings.bundle
var version = "Version"

#this will be the text displayed in title
longVersion=$(/usr/libexec/PlistBuddy -c "Print CFBundleVersion" "${INFOPLIST_PATH}")
shortVersion=$(/usr/libexec/PlistBuddy -c "Print :CFBundleShortVersionString" ${TARGET_BUILD_DIR}/${INFOPLIST_PATH})
buildVersion="$shortVersion.$longVersion"

path="${WRAPPER_NAME}/Settings.bundle/Root.plist"

settingsCnt=`/usr/libexec/PlistBuddy -c "Print PreferenceSpecifiers:" ${path} | grep "Dict"|wc -l`

for (( idx=0; idx<$settingsCnt; idx++ ))
do
#echo "Welcome $idx times"
val=`/usr/libexec/PlistBuddy -c "Print PreferenceSpecifiers:${idx}:Key" ${path}`
#echo $val

#if ( "$val" == "Version" )
if [ $val == "Version" ]
then
#echo "the index of the entry whose 'Key' is 'version' is $idx."

# now set it
/usr/libexec/PlistBuddy -c "Set PreferenceSpecifiers:${idx}:DefaultValue $buildVersion" $path

# just to be sure that it worked
ver=`/usr/libexec/PlistBuddy -c "Print PreferenceSpecifiers:${idx}:DefaultValue" $path`
#echo 'PreferenceSpecifiers:$idx:DefaultValue set to: ' $ver

fi

done

Example entry in Root.plist

    <dict>
        <key>Type</key>
        <string>PSTitleValueSpecifier</string>
        <key>Title</key>
        <string>Version</string>
        <key>DefaultValue</key>
        <string>We Rock</string>
        <key>Key</key>
        <string>Version</string>
    </dict>

Working sample Root.plist entry

与他有关 2024-07-27 23:24:49

我相信您可以使用类似于我在 这个答案中描述的方式来完成此操作(基于这篇文章)。

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

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

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

当这些值在项目中发生更改时,这应该可以实现替换变量的技巧。

I believe you can do this using a way that's similar to what I describe in this answer (based on this post).

First, you can make VersionValue a variable within Xcode by renaming it to ${VERSIONVALUE}. Create a file named versionvalue.xcconfig and add it to your project. Go to your application target and go to the Build settings for that target. I believe that you need to add VERSIONVALUE as a user-defined build setting. In the lower-right-corner of that window, change the Based On value to "versionvalue".

Finally, go to your target and create a Run Script build phase. Inspect that Run Script phase and paste in your script within the Script text field. For example, my script to tag my BUILD_NUMBER setting with the current Subversion build is as follows:

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

This should do the trick of replacing the variable when these values change within your project.

踏月而来 2024-07-27 23:24:49

这些是我必须在 Xcode 12.2 的 swift 项目中使用的变量

version=$(/usr/libexec/PlistBuddy -c "Print CFBundleShortVersionString" "$PROJECT_DIR/$INFOPLIST_FILE")
build="$CURRENT_PROJECT_VERSION"

/usr/libexec/PlistBuddy -c "Set PreferenceSpecifiers:0:FooterText Version $version" "$CODESIGNING_FOLDER_PATH/Settings.bundle/ServerURLSettings.plist"
/usr/libexec/PlistBuddy -c "Set PreferenceSpecifiers:0:FooterText Version $version($build)" "$CODESIGNING_FOLDER_PATH/Settings.bundle/DeveloperSettings.plist"

These are the variables I had to use for a swift project with Xcode 12.2

version=$(/usr/libexec/PlistBuddy -c "Print CFBundleShortVersionString" "$PROJECT_DIR/$INFOPLIST_FILE")
build="$CURRENT_PROJECT_VERSION"

/usr/libexec/PlistBuddy -c "Set PreferenceSpecifiers:0:FooterText Version $version" "$CODESIGNING_FOLDER_PATH/Settings.bundle/ServerURLSettings.plist"
/usr/libexec/PlistBuddy -c "Set PreferenceSpecifiers:0:FooterText Version $version($build)" "$CODESIGNING_FOLDER_PATH/Settings.bundle/DeveloperSettings.plist"
比忠 2024-07-27 23:24:49

对我来说,这是最简单的解决方案:

在复制捆绑资源步骤

Shell 之前添加新的脚本构建阶段: /usr/bin/env python

内容:

#! /usr/bin/env python
import os
from AppKit import NSMutableDictionary

# Key to replace
settings_key = 'version_preference' # the key of your settings version

# File path
settings_path = os.environ.get('SRCROOT') + "/TheBeautifulNameOfYourOwnApp/Settings.bundle/Root.plist"

# Composing version string
version_string = os.environ.get('MARKETING_VERSION') + " (" + os.environ.get('CURRENT_PROJECT_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'] = version_string

# Save new settings
settings_plist.writeToFile_atomically_(settings_path, True)

For me this was the easiest solution:

Add new script build phase before Copy Bundle Resources step

Shell: /usr/bin/env python

Content:

#! /usr/bin/env python
import os
from AppKit import NSMutableDictionary

# Key to replace
settings_key = 'version_preference' # the key of your settings version

# File path
settings_path = os.environ.get('SRCROOT') + "/TheBeautifulNameOfYourOwnApp/Settings.bundle/Root.plist"

# Composing version string
version_string = os.environ.get('MARKETING_VERSION') + " (" + os.environ.get('CURRENT_PROJECT_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'] = version_string

# Save new settings
settings_plist.writeToFile_atomically_(settings_path, True)
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文