将许可证部分添加到iOS设置捆绑包的最佳方法


116

我的iOS应用程序使用了许多在Apache 2.0和类似许可证下获得许可的第三方组件,这需要我包含各种文本,例如:

* Redistributions in binary form must reproduce the above copyright
  notice, this list of conditions and the following disclaimer in the
  documentation and/or other materials provided with the distribution.

将此信息放在设置捆绑包中的“许可证”子条目下似乎有一个合理的先例(在ipad的Facebook,页面,主题演讲,数字和Wik​​ipanion上似乎都可以做到这一点)。

我在努力实现相同目标方面有些挣扎;我似乎需要一行一行地分割文本,然后一次输入xcode一行(并且在编辑plists时,xcode4似乎有崩溃的问题)。

似乎几乎可以肯定某个地方的脚本可以做,或者我错过了一些简单的方法来完成。

Answers:


192

我想我现在已经设法解决了遇到的所有问题。

  • 似乎最好使用组元素标题来持有许可证(这是Apple在iWork应用程序中所做的事情)。但是,它们的长度是有限制的(并且我还没有确切发现限制是什么),因此您需要将每个许可证文件分成多个字符串。
  • 您可以通过在其中包含换行符的方式来创建换行符(例如,以其他方式称为^ M,\ r或0x0A)
  • 确保不包含任何文字中间文本。如果这样做,文件中的某些或所有字符串将被静默忽略。

我有一个便捷脚本,可用来帮助生成.plist和.strings文件,如下所示。

要使用它:

  1. 在您的项目下创建一个“许可证”目录
  2. 将脚本放入该目录
  3. 将每个许可证放入该目录(每个文件一个),文件名以.license结尾
  4. 对许可证执行任何必要的重新格式化。(例如,在行首删除多余的空格,确保段落中间没有换行符)。每个段落之间应有一个空白行
  5. 转到许可证目录并运行脚本
  6. 编辑设置包Root.plist,以包含一个名为“致谢”的子部分

这是脚本:

#!/usr/bin/perl -w

use strict;

my $out = "../Settings.bundle/en.lproj/Acknowledgements.strings";
my $plistout =  "../Settings.bundle/Acknowledgements.plist";

unlink $out;

open(my $outfh, '>', $out) or die $!;
open(my $plistfh, '>', $plistout) or die $!;

print $plistfh <<'EOD';
<?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>StringsTable</key>
        <string>Acknowledgements</string>
        <key>PreferenceSpecifiers</key>
        <array>
EOD
for my $i (sort glob("*.license"))
{
    my $value=`cat $i`;
    $value =~ s/\r//g;
    $value =~ s/\n/\r/g;
    $value =~ s/[ \t]+\r/\r/g;
    $value =~ s/\"/\'/g;
    my $key=$i;
    $key =~ s/\.license$//;

    my $cnt = 1;
    my $keynum = $key;
    for my $str (split /\r\r/, $value)
    {
        print $plistfh <<"EOD";
                <dict>
                        <key>Type</key>
                        <string>PSGroupSpecifier</string>
                        <key>Title</key>
                        <string>$keynum</string>
                </dict>
EOD

        print $outfh "\"$keynum\" = \"$str\";\n";
        $keynum = $key.(++$cnt);
    }
}

print $plistfh <<'EOD';
        </array>
</dict>
</plist>
EOD
close($outfh);
close($plistfh);

设置您的Settings.bundle

如果尚未创建Settings.bundle,请转到文件->新建->新建文件...

在“资源”部分下,找到“设置捆绑包”。使用默认名称并将其保存到项目的根目录。

展开Settings.bundle组,然后选择Root.plist。您将需要添加一个新部分,其键Preference Items的类型将为Array。添加以下信息:

在此处输入图片说明

Filename关键点,是由该脚本创建的plist中。您可以将更title改为所需的内容。

在构建时执行脚本

另外,如果希望在构建项目时运行此脚本,则可以将构建阶段添加到目标中:

  1. 转到您的项目文件
  2. 选择目标
  3. 单击构建阶段选项卡
  4. 在该窗格的右下角,单击“添加构建阶段”
  5. 选择“添加运行脚本”
  6. 将您的perl脚本拖放到脚本部分中。修改为如下所示:
  1. cd $SRCROOT/licenses$SRCROOT指向项目的根)
  2. ./yourScriptName.pl

完成之后,可以Run Script在构建过程中更快地拖动构建阶段。您需要先将其向上移动,Compile Sources以便编译和复制设置捆绑包的更新。

iOS 7更新: iOS 7似乎处理“ Title”键的方式有所不同,并且使呈现的文本混乱。要修复生成的Acknowledgements.plist,需要使用“ FooterText”键而不是“ Title”。这如何更改脚本:

for my $str (split /\r\r/, $value)
{
    print $plistfh <<"EOD";
            <dict>
                    <key>Type</key>
                    <string>PSGroupSpecifier</string>
                    <key>FooterText</key> # <= here is the change
                    <string>$keynum</string>
            </dict>
 EOD

    print $outfh "\"$keynum\" = \"$str\";\n";
    $keynum = $key.(++$cnt);
}

1
真是个好主意!在迅速意识到我需要自动化解决方案之前,我开始手动进行此操作,尤其是由于严苛的组标题长度限制。
坎贝尔希尔顿酒店,

9
需要注意的一件事:“文件名”是密钥的显示形式。实际的密钥是“文件”。如果未显示子窗格,请右键单击并选择“显示原始键/值”,并确保键名称为“文件”。
atticus 2012年

10
太好了,谢谢。我在“运行脚本”块中使用了“ cd“ $ SRCROOT / Licenses /””,如果您有多个人在一个项目上工作,效果会更好。
克里斯,2012年

9
阅读devforums.apple.com/message/894791#894791如果您使用此与iOS7。具体来说,您可能需要将<key> Title </ key>更改为<key> FooterText </ key>才能使其看起来正常。
esilver 2013年

2
如何使其成为子窗格:在“首选项”中创建“项0”。看起来您无法选择“子窗格”作为类型,但是您要做的是在Item 0(Item 0的子项目)下创建一个项目,并且第一个项目具有键“ Type”。为了简化操作,请右键单击它,然后选择“显示原始键/值”。您要将Type的值设置为PSChildPaneSpecifier。取消设置“显示原始键/值”后,它现在将显示“子窗格”,即使使用项目0的名称,即“其0(子窗格-)”。这就是你想要的。
2015年

36

这是@JosephH提供的相同解决方案(不带翻译),但对于喜欢python而不是perl的任何人,都使用Python完成

import os
import sys
import plistlib
from copy import deepcopy

os.chdir(sys.path[0])

plist = {'PreferenceSpecifiers': [], 'StringsTable': 'Acknowledgements'}
base_group = {'Type': 'PSGroupSpecifier', 'FooterText': '', 'Title': ''}

for filename in os.listdir("."):
    if filename.endswith(".license"):
        current_file = open(filename, 'r')
        group = deepcopy(base_group)
        title = filename.split(".license")[0]
        group['Title'] = title
        group['FooterText'] = current_file.read()
        plist['PreferenceSpecifiers'].append(group)

plistlib.writePlist(
    plist,
    "../Settings.bundle/Acknowledgements.plist"
)

这个答案需要更多的投票。Python语法<3Perl语法。;)
Ricardo Sanchez-Saez 2014年

5
current_file = codecs.open(filename, 'r', 'utf-8')Unicode许可证。
user2821144 2015年

谢谢!我基于此版本创建了一个新版本,非常适合迦太基。它还从许可证文本中删除了一些不必要的换行符。看看:gist.github.com/Zyphrax/0d015c618d46093b4f815e62a6a33969
Zyphrax

1
我在其中做了更多工作,请参见:github.com/Building42/AckAck
Zyphrax

15

或者,对于使用CocoaPods的用户,它将为Podfile中指定的每个目标生成一个“ Acknowledgements” plist,其中包含该目标中使用的每个Pod的许可详细信息(假设详细信息已在Pod规范中指定)。可以添加到iOS设置捆绑包的属性列表文件。

还正在进行一些项目,以允许这些数据转换并显示在应用程序中:

https://github.com/CocoaPods/cocoapods-install-metadata

https://github.com/cocoapods/CPDAcknowledgements



请注意,Cocoapods Wiki的输入文件名为Pods-Acknowledgements.plist,但实际上是作为Pods-acknowledgements.plist生成的(小写的“ a”)。如果文件系统区分大小写,则使用错误的大小写将中断pod安装。
凯勒

14

我以为我会把我的迭代放在混合在一起的Sean很棒的python代码上。主要区别在于,它采用输入目录,然后递归地在其中搜索LICENSE文件。它从LICENSE文件的父目录派生标题值,因此可与cocoapods一起很好地发挥作用。

这样做的动机是创建一个构建脚本,以在添加或删除Pod时自动使我的应用程序的法律部分保持最新。它还做一些其他事情,例如从许可证中删除强制换行符,以便使段落在设备上看起来更好一些。

https://github.com/carloe/LicenseGenerator-iOS

在此处输入图片说明


8

我用@JosephH脚本在Ruby中编写了一个脚本。我个人认为,此版本将更好地代表各个开源项目。

Wisit iOS-AcknowledgementGenerator下载脚本和示例项目。

这是确认在您的应用程序中的样子:

Settings.app Settings.bundle 致谢 在此处输入图片说明


2

这是JosephH回答的附录。(我没有代表对此发表评论)

我不得不<key>StringsTable</key> <string>Acknowledgements</string> 向下移动 到</dict>Perl脚本中的最后一个之上。

在进行此修改之前,App中的“确认”部分为空,并且XCode无法读取生成的Acknowledgements.plist。(“由于格式不正确,无法读取数据。”)

(XCode 6.3.2 iOS 8.3)


2

Sean中的Python脚本在此线程中有效。但是有一些基本知识要知道。

  1. 在Xcode中,右键单击Project Navigator树顶部的项目名称,然后添加一个New Group。这将在您的项目中放置一个新文件夹。
  2. 在此处添加Sean的脚本,并确保将其另存为:Acknowledgements.py。
  3. 确保您的系统上安装了Python。我正在使用Mac。
  4. 将第一个许可证文件添加到您在1.中创建的文件夹中。使其变得简单,就像在文件中只说一个单词,例如:测试。将其另存为Test1.license文件夹中。
  5. 按照上面的JosephH设置您的Settings.bundle。
  6. 使用终端应用程序将CD光盘复制到在1中创建的文件夹。
  7. 运行脚本。输入:python Acknowledgements.py。如果没有错误,它将立即返回到终端提示。在将任何运行脚本添加到Build之前,请执行所有这些操作。
  8. 生成并运行您的应用程序。
  9. 双击iPhone主屏幕按钮,然后杀死“设置”。在设置重新启动之前,通常不会选择应用程序的设置更改。
  10. 重新启动“设置”后,转到您的应用并查看其是否有效。
  11. 如果一切正常,请缓慢添加更多许可证文件,但每次都运行脚本。由于文件中包含某些字符,您可能会在运行脚本时出错,因此调试的简单方法是添加文件,运行脚本,查看其是否有效并继续。否则,请编辑.license文件中的所有特殊字符。
  12. 按照上面的说明,我没有获得“运行构建脚本”的工作。但是,如果您不经常更改.license文件,则此过程可以正常进行。

1

Ack Ack:确认Plist生成器不久前
,我创建了一个Python脚本,该脚本扫描许可证文件并创建一个不错的Acknowledgments plist,您可以在Settings.plist中使用它。它为您完成了很多工作。

https://github.com/Building42/AckAck

特征

  • 检测Carthage和CocoaPods文件夹
  • 检测现有的定制许可证持有人
  • 通过删除不必要的新行和换行符来清理许可证文本
  • 提供许多自定义选项(--help有关详细信息,请参阅)
  • 同时支持Python v2和v3

安装

wget https://raw.githubusercontent.com/Building42/AckAck/master/ackack.py
chmod +x ackack.py

./ackack.py

屏幕截图

致谢

如果您有改进的建议,请随时在GitHub上发布问题或提出请求!

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.