向 iOS 设置包中添加许可证部分的最佳方法

我的 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.

似乎有一个合理的先例可以将这些信息放在设置包中的“ License”子条目下(在 ipad 的 facebook、页面、主题演讲、数字和 wikipanion 上似乎都是这样做的)。

不过,实际上我也在努力做到这一点; 我似乎需要把文本一行一行地拆分,然后一次输入 xcode (xcode4在编辑 plist 时似乎遇到了崩溃的问题)。

这似乎是那种几乎肯定有某个脚本可以执行的事情,或者是我错过的一些简单的方法。

47574 次浏览

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

  • 似乎最好使用组元素标题来保存许可证(这是苹果在 iWork 应用程序中的做法)。然而,这些许可证的长度是有限制的(我还没有确切地发现这个限制是什么) ,因此您需要将每个许可证文件分成多个字符串。
  • 您可以在其中创建一个换行符,方法是包含一个文字回车符(即。或称为 ^ M,r 或0x0A)
  • 确保不包括任何文字的中间文本。如果这样做,文件中的部分或全部字符串将被无声地忽略。

我使用了一个方便的脚本来帮助生成. plist 和. string 文件,如下所示。

使用方法:

  1. 在项目下创建一个“许可证”目录
  2. 将脚本放入该目录
  3. Put each license into that directory, one per file, with filenames that end .license
  4. Perform any necessary reformatting on the licenses. (eg. remove extra spaces at the beginning of lines, ensure that there are no line breaks mid-paragraph). There should be a blank line in-between each paragraph
  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,请转到 File —— > New —— > New File..。

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

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

enter image description here

Filename键指向此脚本创建的 plist。你可以改变 title到任何你想要的。

在构建时执行脚本

此外,如果希望在生成项目时运行此脚本,可以向目标添加一个生成阶段:

  1. 转到你的项目文件
  2. 选择目标
  3. 单击“生成阶段”选项卡
  4. 在该面板的右下角,单击“添加构建阶段”
  5. 选择’添加运行脚本’
  6. 将 perl 脚本拖放到脚本的部分:
  1. cd $SRCROOT/licenses($SRCROOT指向项目的根)
  2. ./yourScriptName.pl

完成这项工作后,可以在构建过程中更快地拖动 Run Script构建阶段。您需要在 Compile Sources之前将它向上移动,以便编译并复制对设置包的更新。

IOS7的更新: iOS7似乎处理“ Title”键的方式不同,并且正在扰乱呈现的文本。要修复这个问题,需要使用“ 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);
}

Here's the same solution that @JosephH provided (without translations), but done in Python for anyone who prefers python over perl

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

受@JosephH script 的启发,我用 Ruby 编写了一个脚本。 This version will, in my own opinion, better represent the individual open source projects.

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

下面是你的应用程序中的致谢:

Settings.app Settings.bundle Acknowledgements enter image description here

作为替代方案,对于那些使用 CocoaPods 的用户,它将为你的 Pod 文件中指定的每个目标生成一个“鸣谢”列表,其中包含该目标中使用的每个 Pod 的许可证详细信息(假设详细信息已经在 Pod 规范中指定)。可以添加到 iOS 设置包的属性列表文件。

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

Https://github.com/cocoapods/cocoapods-install-metadata

Https://github.com/cocoapods/cpdacknowledgements

我觉得我应该把我的迭代加到 Sean 的超赞的 Python 代码里。主要区别在于,它接受一个输入目录,然后递归地搜索 LICENSE 文件。它从 LICENSE 文件的父目录派生 title 值,因此它可以很好地处理 cocoapods。

The motivation was to create a build script to automatically keep the legal section of my app up to date as I add or remove pods. It also does some other things like remove forced newlines from licenses so the paragraphs look a bit better on the devices.

Https://github.com/carloe/licensegenerator-ios

enter image description here

这是约瑟夫回答的附录

我不得不搬家 <key>StringsTable</key> < 字符串 > 致谢 直到 Perl 脚本中最后一个 </dict>之上。

在此修改之前,应用程序中的鸣谢部分是空的,XCode 无法读取生成的鸣谢. plist。(“数据无法读取,因为格式不正确。”)

(XCode 6.3.2 iOS 8.3)

这个线程中 Sean 编写的 Python 脚本可以工作,但是有一些基本的东西需要了解。

  1. 在 Xcode,右键单击“项目导航器”树顶部的项目名称,然后添加一个“新建组”。这将在项目中放置一个新文件夹。
  2. 在这里添加肖恩的脚本,并确保保存为: acknowledgements.py。
  3. 确保你的系统安装了 Python,我用的是 Mac。
  4. 将第一个许可文件添加到您在1中创建的文件夹中。让它变得简单,就像文件中只有一个单词,比如: 测试。将其保存在 Test1.License 文件夹中。
  5. 按照上面的 JosephH 设置 Settings.bundle。
  6. 使用您的终端应用程序 CD 到您在1中创建的文件夹。
  7. Run the script. Type: python Acknowledgements.py. If you get no errors it will return right back to the Terminal prompt. Do all of this before adding any run script to the Build.
  8. 构建并运行您的应用程序。
  9. 双击 iPhone 主页按钮并关闭设置。在设置重新启动之前,它通常不会收到应用程序的设置更改。
  10. 重新启动设置后,进入应用程序,看看它是否工作。
  11. 如果这些都有效,那么慢慢地添加更多的许可文件,但是每次都要运行脚本。由于文件中的某些字符,可能会导致运行脚本时出现错误,因此简单的调试方法是添加一个文件,运行脚本,查看它是否工作并继续。否则,将任何特殊字符从。许可证文件。
  12. 我没有得到运行生成脚本的工作按照上面的说明。但是如果不更改。许可证文件。

确认列表生成器
不久前,我创建了一个 Python 脚本,它可以扫描许可文件并创建一个很好的鸣谢列表,您可以在 Settings.plist 中使用它。它为你做了很多工作。

Https://github.com/building42/ackack

Features

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

安装

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

Run

./ackack.py

截图

Acknowledgements

如果您有改进的建议,欢迎在 GitHub 上发布问题或请求!

Aknow list 是一个强大的 CocoaPod 候选者,在撰写本文时,它被积极地维护。如果您同意将许可证放在应用程序中而不是放在设置包中,那么它将自动执行此许可证。这对我正在做的项目很有帮助。

I had to modify sean's script for modern python3:

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"):
with open(filename, 'r') as current_file:
group = deepcopy(base_group)
title = filename.split(".license")[0]
group['Title'] = title
group['FooterText'] = current_file.read()
plist['PreferenceSpecifiers'].append(group)


with open("Acknowledgements.plist", "wb") as f:
plistlib.dump(plist, f)