【问题标题】:Add files to an Xcode project from a script?从脚本将文件添加到 Xcode 项目?
【发布时间】:2009-09-03 03:51:36
【问题描述】:

现在我正在使用一些脚本来生成我作为资源包含在 Xcode 中的文件。问题是我正在运行脚本,然后从项目中删除,然后重新添加到项目中。一定有办法自动化这最后一步,以便脚本可以生成文件并自动将它们添加到我的 xcode 项目中。

我正在使用 bash,但任何语言示例都会有所帮助。

谢谢, 安德鲁

【问题讨论】:

  • @Andrew:你设法让它工作了吗?我很好奇最终的结果。

标签: xcode scripting project


【解决方案1】:

我和安德鲁有类似的需求。我需要能够在不提前知道这些资源的情况下从脚本中包含资源。这是我想出的解决方案:

在“复制捆绑资源”之后添加一个新的运行脚本构建阶段,其中包含以下命令:

find -L ${SRCROOT}/SomeDerivedResources \
    -type f -not -name ".*" \
    -not -name "`basename ${INFOPLIST_FILE}`" \
    | xargs -t -I {} \
    cp {} ${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/

看起来很吓人,但让我们分解一下:

find -L ${SRCROOT}/SomeDerivedResources

这会爬取我们源根目录中的 SomeDerivedResources 目录(-L 告诉它遵循符号链接)

-type f

只包含常规文件

-not -name ".*"

忽略以点开头的文件

-not -name "`basename ${INFOPLIST_FILE}`"

在我的例子中,我的 Info plist 位于我的 SomeDerivedResources 目录中,因此我们需要排除该文件被复制到我们的产品中

| xargs -t -I {}

使用-tfind 的结果传送到xargs(将结果命令回显到stderr,以便它们显示在我们的构建日志中),-I(为每个输入文件运行一次命令)并使用@ 987654332@ 作为我们的参数占位符

cp {} ${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/

最后,将找到的每个文件(用{}表示)复制到我们产品的资源目录。

我在键入此内容时意识到,使用 rsync 设置而不是 cp 可能会阻止我们在每次构建时复制资源。如果您的资源非常大,可能值得研究一下。

(此外,由于某些原因,文件夹引用无法满足我的需要。第一,我的图标位于我的 DerivedResources 目录中,并且将它们放在捆绑包的子目录中似乎不起作用。另外,我理想地想要能够使用[UIImage imageNamed:@"MyAwesomeHappyImage.png"]-pathForResource:ofType:(我的一些文件进一步嵌套在我的 DerivedResources 目录中)。如果您的需求不包含这些限制,我高度建议您去文件夹参考路线。)

【讨论】:

  • Awesomeness for: "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/" --- 正是我需要的,但在 Apple 的文档中找不到。我不知道为什么 Xcode4 在添加输出文件部分时懒得自动执行此操作:( :(
  • 与无法访问捆绑包中的子目录有关 - 这可能是因为捆绑包和子目录具有相同的名称。如果您不使用完全相同的名称,它应该可以正常工作。
  • 我正在使用这个脚本,它运行良好!不过有一件事......当我们使用这种方法修改 .app 文件时,苹果似乎不会让你在设备上安装该项目,因为它被篡改了。有什么建议吗?
  • @kevinl 您是否在 Xcode 中将脚本作为“运行脚本”构建阶段运行?代码签名发生在这些步骤之后,所以它应该可以正常运行。
  • @BenCochran 啊,是的。那是问题的一部分。现在一切正常,谢谢。
【解决方案2】:

这可以通过向您的应用程序添加一个新的构建阶段来完成。

  1. 在 Xcode 项目浏览器中,找到应用程序的目标,然后展开它以显示所有构建阶段。

  2. 为您的目标添加一个新的"run script" build phase。最简单的方法是右键单击目标并选择“Add/New Build Phase/New Run Script Build Phase”

  3. 添加新的构建阶段应该会打开一个检查器窗口。在此窗口中,您可以输入整个 shell 脚本,也可以只输入命令行来运行脚本。

  4. 这是黄金:在检查器窗口的底部,您可以指定输入文件和输出文件。指定输入文件会自动设置依赖关系(只有在修改了某些输入文件时才会执行 shell 脚本)。指定输出文件会自动将依赖项传播到这些文件。当你的 shell 脚本运行时,Xcode 知道它需要处理那些被 shell 脚本修改过的文件。

  5. 确保将新的构建阶段拖到阶段列表的顶部,如下面的屏幕截图所示。如果您需要将这些资源文件包含在包中,则顺序很重要。

  6. 保存、构建、提交到存储库、要求加薪、呼吸新鲜空气并度过美好的一天! :)

【讨论】:

  • 谢谢!就我而言,我不提前知道输出文件。我希望在某种子组中动态地将文件添加到项目中。那可能吗?还是我错过了您的示例?
  • 嗯。这很棘手。将文件添加到项目中的目的是什么?它们只需要复制到应用程序包中,还是需要与其余代码一起编译?我可以想到一些解决方案,但我需要更多地了解如何在文件生成后使用它们。
  • 安德鲁,你找到解决方案了吗?
  • 还没有,添加脚本的东西非常有用,我现在已经做到了,但我仍然找不到自动将文件添加到项目的方法。有什么想法吗?
  • 那些链接失效了
【解决方案3】:

对于那些有大量文件的人,为了避免重新复制(或重新检查)每个文件,正如@Ben Cochran 所建议的(非常感谢伟大的脚本),这是使用 rsync 的方法:

【讨论】:

  • 我遇到了一个问题,我需要将我的应用程序包包含到由单独服务提供的大量资源文件中,但每个版本都会更改,这完美地解决了我的问题。
  • @KevinJamesHunt 我也有类似的要求,我有一组 js 文件作为文件夹添加到 Resources 目录中。每次发生更改时,我都会手动复制和替换。相反,我想自动化,假设文件位于服务器中的某个位置,那么有没有办法运行一个脚本,该脚本将从服务器下载内容并将其复制到资源文件夹。
【解决方案4】:

基本上,只需将文件复制到主包中

在这种情况下,只需添加对项目的文件夹引用(在项目文件夹中创建一个文件夹,然后将其拖到项目的“资源”组中(在“文件和组”列表中;然后在出现的工作表中选择“为任何添加的文件夹创建文件夹引用”单选按钮),Xcode 将在构建时将文件夹及其所有内容复制到目标包中。

请注意:如果您使用此方法添加图像子文件夹,则必须在图像名称前加上子文件夹名称才能使用“[UIImage imageNamed:]”。例如,如果您在名为“MyImages”的子文件夹中有一个名为“Rendezvous.png”的图像:

`

// this won't work
UIImage * image = [UIImage imageNamed:@"Rendezvous"];
if (image) {
    NSLog(@"Found Rendezvous!");
} else {
    NSLog(@"Didn't find Rendezvous.");
}

// but this will!
image = [UIImage imageNamed:@"MyImages/Rendezvous"];
if (image) {
    NSLog(@"Found MyImages/Rendezvous!");
} else {
    NSLog(@"Didn't find MyImages/Rendezvous.");
}

`

【讨论】:

  • 这也完全可行,而且容易得多:) 它唯一改变的是你不能使用像 [UIImage imageNamed:] 这样的函数,因为文件保留在包中的文件夹中。但仍然是一个很好的解决方案。
  • 其实还是可以用"[UIImage imageNamed:]";您只需要在图像名称中包含子文件夹名称。例如:'[UIImage imageNamed:@"MyImagesFolder/MyImageName"];'。
  • 如果您想添加一些代码类(例如.swift),文件夹解决方案可以完美运行。 PS。现在你需要按下选项,当“添加新文件”屏幕出现时,选择你是否要使用文件夹或组
【解决方案5】:

如果您的系统某处已经有这些文件,相对于您的源根目录,您可以随时添加a "Copy Files" phase。这将允许您指定应从中复制资源的目录。

您可以将此与已提供给您的构建脚本阶段答案结合使用。例如,运行一个脚本将您的资产从 Subversion 检出到项目的子目录中,然后执行从“$(SRCROOT)/Assets”复制的 Copy Files 阶段。

【讨论】:

  • 好主意。再加上上面的例子,这正是我当时所需要的,我肯定会在下次更新我的应用时这样做。
  • @Andrew 你能解释一下你是如何在 XCode 4 上做到这一点的吗?非常感谢!
  • 只能指定目标文件夹,不能指定源文件夹。
【解决方案6】:

我知道这有点晚了,但我刚刚遇到this article 解释如何做一些听起来像你正在寻找的事情。

【讨论】:

    【解决方案7】:

    我发现自己在使用 Ionic Capacitor 时遇到了类似的情况。我期待的是在“复制捆绑资源”捆绑阶段包含文件。我发现 Ionic 已经为您打包了一些内容,如果您将文件滑入此文件夹,您也会将其包含在内。

    您看到 App 文件夹包含了吗?它是我们的入口点。

    为了包含它,我添加了一个执行以下操作的脚本:

    cp -Rf ./includes/yourfolder/ ./ios/App/App/
    

    【讨论】:

      【解决方案8】:

      我设法解决了这个问题

      “代码对象根本没有签名”

      在构建上传到 iTunes Connect 的过程中可能会遇到这种情况:

      我没有将脚本包含在捆绑资源中。

      因此脚本(在本例中为 Python 文件)在构建期间执行,(它执行它必须做的事情)但它不包含在应用程序的捆绑包中。

      怎么办?

      打开构建阶段,转到复制捆绑资源部分,选择文件并使用 (-) 将其删除。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2013-12-17
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-06-15
        • 2013-03-11
        • 2013-12-03
        • 1970-01-01
        相关资源
        最近更新 更多