【问题标题】:NSPasteboard and simple custom dataNSPasteboard 和简单的自定义数据
【发布时间】:2011-08-30 13:11:36
【问题描述】:

我很难让 NSPasteboard 工作,所以请原谅我缺乏理解。

我想要的只是一种简单的方法,可以在粘贴板中写入和检索仅适用于我的应用程序的 NSUInteger 值。我所做的只是在我的应用程序中拖放一个项目,所以我在粘贴板中需要的只是项目的 ID。

我曾尝试研究 NSPasteboardItemDataProvider 和 NSPasteboardItem 以及 NSData,但它们都以复杂的方式来做如此简单的事情。事实上,我不知道做如此简单的事情的正确方法是什么——周围的每个样本似乎都处理字符串类型,或者更复杂的事情。 [NSMutable SetData] 选择器似乎也不存在,即使代码中没有警告。

如果有人能指出我正确的方向,我将不胜感激。 :)

编辑:我正在使用 [dragImage ...] 来帮助我进行拖动操作。

【问题讨论】:

  • 你为什么要使用 NSPasteboard 来做类似的事情?如果您不想/需要应用程序之外的数据,这是一个非常糟糕的决定。您应该使用属性、委托、通知或至少 NSUSerDefaults。
  • 我仍在学习如何使用 Cocoa,所以我可能并不总是选择最好的方法。我正在执行拖放操作以将一个(多个)视图从一个区域移动到另一个区域,所以我认为这是实现它的好方法。它还具有通常用于此类操作的漂亮回滚图像。
  • @fichek:NSPasteboard 实现拖放的一部分。
  • @PeterHosey 是的,我后来才注意到他指的是 Mac,抱歉 :)

标签: cocoa macos nspasteboard


【解决方案1】:

NSPasteboard 有两种使用方式。

旧方法:自己将数据固定到板上

首先,您必须declare the types that you will put on the pasteboard。您还可以指定一个“拥有”粘贴板的对象,这意味着这是在粘贴板上放置内容的对象。

下一步是将数据放在粘贴板上。这一步是可选的。

“可选?!”,你问。是的:如果您没有将您声明的任何类型的数据放在粘贴板上,并且粘贴板随后需要该数据(粘贴/删除),那么the pasteboard will ask you (the owner) for it。这被称为承诺数据,当数据的复制(大)或生成成本很高时,这很好。

有五种方法可以把东西放在粘贴板上(除了被要求):

  • As a string. 仅适用于纯文本。粘贴板将根据需要将其转换为各种编码。
  • As a property list. 仅适用于属性列表(是的,这是一直强制执行的,因此图像数组不计算在内),或者您可以在属性列表之间转换的东西。这可以包括您自己的对象,如果您在其中实现的话。
  • As raw data. 适用于现有数据类型,例如图像类型(PNG、JPEG 等)和 A/V 类型(MPEG-4 等)。
  • As the contents of a file identified by path. 仅当您拖动/复制的内容已经是文件时才有效。
  • As the contents of a file wrapper. 如果您还没有使用文件包装器,您可以放心地忽略它。

较新的方法:将对象固定到板上并让它们将自己变成数据

Snow Leopard 中引入的新热点是让您的对象能够自己将自己写入粘贴板。这确实要求他们了解您希望在粘贴板上显示的关于他们自己的所有信息,包括标识符。

您需要使您的对象同时符合NSPasteboardWritingNSPasteboardReading

既然您知道了旧的方式,那么编写协议看起来会非常熟悉。粘贴板询问您的对象what types it would represent itself as,然后是asks it for a property-list object for each type。 (该协议还提供了一种承诺类型的方法,而不是立即请求它们的数据。)

要将符合 NSPasteboardWriting 的对象复制到粘贴板,请向粘贴板发送 clearContents 消息(在新方式中是必需的,在旧方式中是可选的),然后 writeObjects: 传递要复制的对象数组.

如您所料,阅读协议是相反的。要粘贴,请发送粘贴板a readObjectsForClasses:options: message。粘贴板询问每个类what types it would recognize,然后(可选)尝试instantiate one or more of them from what's on the pasteboard

这样做的缺点是,特别是在涉及重用标识符的情况下,它最终可能会破坏模型层与控制器层的分离。 Your reading initializer 如果您希望它返回具有该标识符的现有对象,则需要知道如何处理该标识符。这意味着它需要与控制器对话(不好)或复制控制器的查找代码(更糟)。

我不知道用新协议实现 move 拖放(包括但不限于重新排序)而不遇到此问题的好方法。对于复制拖放(包括但不限于跨进程),这很好,因为您不需要标识符 - 只需在一端生成数据并在另一端创建新副本.

新方法的好处是处理多个项目更加理智。在旧的方式中,只有一个“项目”——实际上,根本没有任何项目的概念——有多种类型。如果您想复制或拖动多个事物,您可以创建一个数组并将其复制为某种类型的单个属性列表,然后在另一端从该单个属性列表中重新创建/检索多个事物。较新的方式明确支持一个或多个项目;复制多个内容时,您只需将它们全部传递给writeObjects:

您的案例:单个 NSUInteger 标识符

将它装在一个 NSNumber(这是一个属性列表)中,并以旧的方式使用它。

【讨论】:

  • 我在实施新方法时遇到了一些问题。如何将此方法中的自定义对象转换为 plist? - (id)pasteboardPropertyListForType:(NSString *)type。这与我的问题stackoverflow.com/questions/17968573/… 有关
  • 不幸的是,Apple 更改了 URL,几乎所有链接都指向同一个通用页面。
【解决方案2】:

要跟进 Peter Hosey 的回答,请查看我的 GitHub Helium 端口的 PlaylistViewController.swift。该模块处理自定义对象的拖放操作以及与 WKWebView 的交互。

这是一项正在进行中的工作,采用新的闪亮粘贴板。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-08-20
    • 1970-01-01
    • 1970-01-01
    • 2016-04-29
    • 1970-01-01
    • 2011-10-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多