什么是粘贴板?
粘贴板是在应用程序内或应用程序之间交换数据的标准化机制。粘贴板最常见的用途是处理复制和粘贴操作:
当用户在应用程序中选择数据并选择复制(或剪切)菜单项时,所选数据将被放置到粘贴板上。
当用户选择“粘贴”菜单项(在相同或不同的应用程序中)时,粘贴板上的数据将复制到当前应用程序中。
也许不那么明显,粘贴板也支持查找操作,拖动和服务操作也是如此:
当用户开始拖动时,拖动数据将添加到粘贴板中。如果拖动以拖放操作结束,则接收应用程序将从粘贴板检索拖动数据。
如果请求翻译服务,则请求应用程序将要翻译的数据放在粘贴板上。服务检索此数据,执行转换,并将转换后的数据放回粘贴板上。
因为它们可用于在应用程序之间传输数据,所以粘贴板存在于一个与应用程序进程分离的特殊全局内存区域中,这在粘贴板服务器中有更详细的描述。不过,这个实现细节是由NSPasteboard类及其方法抽象出来的。您所要做的就是与粘贴板对象交互。
无论操作如何,您要执行的基本任务是(a)将数据写入粘贴板,(b)从粘贴板读取数据。这些任务在概念上非常简单,但是掩盖了许多重要的细节。实际上,增加复杂性的主要潜在问题是,可能有多种方法来表示数据,这反过来又导致了对效率的考虑。此外,从系统的角度来看,还有其他问题需要考虑。下面几节将讨论这些问题。
名为粘贴板
粘贴板可以是公共的也可以是私有的,可以用于各种目的。在系统范围内,为定义明确的操作提供了几种标准的粘贴板:
NSGeneralBoard,用于剪切、复制和粘贴
nsrulerboard,用于复制和粘贴标尺
nsfontboard,用于剪切、复制和粘贴NSFont对象
NSFindPboard,应用程序特定的查找面板可以共享一个受欢迎的文本值
NSDragPboard,用于图形拖放操作
通常使用系统定义的粘贴板之一
但如有必要,您可以使用pasteboardWithName为超出预定义集的交换创建自己的粘贴板
如果调用具有唯一名称的pasteboardWithUniqueName,则pasteboard服务器将为您提供一个唯一命名的pasteboard。
粘贴板项目
放置在粘贴板上的每一块数据都被视为粘贴板项目。
粘贴板可以容纳多个项目。应用程序可以放置或检索任意数量的项目。
例如,假设浏览器窗口中的用户选择同时包含文本和图像。
粘贴板允许您将文本和图像作为单独的项目复制到粘贴板。
粘贴多个项目的应用程序可以选择只获取支持的项目(例如文本,而不是图像)。
陈述和UTI
粘贴板操作通常在两个不同的应用程序之间执行。
两个应用程序都不了解另一个应用程序以及每个应用程序可以处理的数据类型。
为了最大化共享的可能性,一个粘贴板可以保存同一个粘贴板项目的多个表示形式。
例如,富文本编辑器可以提供复制数据的RTFD、RTF和NSString表示。
添加到粘贴板的项指定它能够提供哪些表示。
项目的每个表示都由不同的唯一类型标识符(UTI)标识。
(UTI是唯一标识特定数据类型的字符串。
有关详细信息,请参见统一类型标识符概述。)
UTI提供了识别数据类型的通用方法。
例如,假设一个应用程序支持富文本和图像的选择。
它可能希望在粘贴板上放置文本选择的富文本和Unicode版本以及图像选择的不同表示形式。
每个项的每个表示都存储有自己的数据,如图1所示。您可以声明自己的uti来支持自己的自定义数据类型。
一般来说,为了最大限度地发挥共享的潜力,粘贴板项目应提供尽可能多的不同表示(请参见自定义数据)。从理论上讲,这可能会导致对效率的担忧,然而,在实践中,通过项目提供不同的表示方式(参见承诺的数据),这些问题得以缓解。
粘贴板阅读器必须找到最适合其功能的数据类型(如果有的话)。通常,这意味着选择可用的最丰富的类型。
在前面的示例中,富文本编辑器可能提供复制数据的RTFD、RTF和NSString表示。支持富文本但没有图像的应用程序应该检索RTF表示;只支持纯文本的应用程序应该检索NSString对象,而图像编辑应用程序可能根本无法使用文本。
承诺的数据
如果粘贴板项支持多个表示法,则将每个表示法的数据放到粘贴板上通常是不切实际的,或者耗费时间和资源。
例如,假设您的应用程序在粘贴板上放置了一个图像。
为了获得最大的兼容性,图像可以提供多种不同的表示形式,包括PNG、JPEG、TIFF、GIF等等。然而,创建每一个表示都需要时间和内存。
与要求项目提供它提供的所有表示不同,粘贴板只要求项目提供的表示列表中的第一个表示。
如果粘贴收件人需要不同的表示形式,则该项可以在请求时生成它。
也可以将项目放置在粘贴板上,并指定由其他对象提供该项目的一个或多个表示形式。
为此,请为粘贴板项目上的特定类型指定数据提供程序。数据提供程序必须符合NSPasteboardItemDataProvider协议协议,以便按需提供相应的数据。
更改计数
更改计数是计算机范围内的变量,每次粘贴板的内容发生更改(声明新所有者)时,该变量都会递增。
为每个命名的粘贴板维护一个独立的更改计数。
通过检查更改计数,应用程序可以确定粘贴板中的当前数据是否与上次接收的数据相同。
changeCount和clearContents方法返回更改计数。
粘贴板服务器
无论数据是在同一个应用程序中的对象之间传输还是在两个不同的应用程序之间传输,在Cocoa应用程序中,接口都是相同的:NSPasteboard对象访问共享存储库,编写器和读卡器在该存储库中交换数据。编写器(称为粘贴板所有者)将数据存储在粘贴板实例上并继续前进。然后,读取器在将来的某个未指定的点异步访问粘贴板。即使是时间,作家也可能不再存在。例如,用户可能已关闭源文档或退出应用程序。
因此,当在两个不同的应用程序之间移动数据时,也就是在两个不同的地址空间之间移动数据时,会涉及到第三个内存空间,因此即使在没有源的情况下,数据也会保持不变。
NSPasteboard提供对第三个地址空间的访问,即始终在后台运行的粘贴板服务器进程(pbs)。
粘贴板服务器维护任意数量的单个粘贴板,以区分多个并发数据传输。
错误
除非NSPasteboard方法说明中特别提到错误,否则与pasteboard服务器的任何通信错误都会引发anNSPasteboardCommunicationException。