NSPasteboard是线程安全的吗?

时间:2010-05-08 21:57:22

标签: cocoa multithreading

从后台线程向NSPasteboard对象写入数据是否安全?我似乎无法在任何地方找到明确的答案。我认为假设是在拖动开始之前将数据写入粘贴板。

背景:
我有一个从Evernote获取数据的应用程序。当应用程序首次加载时,它会获取每个音符的元数据,但不会获取音符内容。然后,注释存根将在大纲视图中列出。当用户开始拖动音符时,音符将传递到后台线程,该后台线程处理从Evernote获取音符内容。拥有主线程阻塞直到获取数据会导致显着的延迟和糟糕的用户体验,所以我有[outlineView:writeItems:toPasteboard:]函数返回YES,而后台线程处理数据并调用主线程将数据写入粘贴板对象。如果在用户将音符丢弃到某处之前传送了音符内容,则一切都很完美。如果用户在处理数据之前将某个音符丢弃......好吧,一切都会永久阻止。让后台线程将数据写入粘贴板是否安全?

2 个答案:

答案 0 :(得分:4)

您可以将数据保证到粘贴板,而无需实际拥有数据。

一种方法是在粘贴板上声明数据的类型,将自己作为粘贴板的所有者传递,并通过提供数据来响应a pasteboard:provideDataForType: message(如果需要,阻止,直到数据到达或未能到达到达)。这意味着您需要记住哪些对象被复制(例如,将它们存储在数组中),以便在承诺到期时从中提取/生成数据。

另一种方式,在Harald Scheirich的回答中提到,是使你的模型对象符合the NSPasteboardWriting protocol,理想情况是在一个类别中(将独立于界面的逻辑与特定于Mac的逻辑分开)。这比旧方法更清晰,但需要Mac OS X 10.6及更高版本。

使用NSPasteboardWriting,您可以通过让模型对象“writingOptionsForType:pasteboard: method返回the NSPasteboardWritingPromised option来实现承诺。他们的 pasteboardPropertyListForType: method将返回数据,或至少尝试 - 如前所述,此方法应该阻止,直到数据到达或无法到达。

哦,并回答标题中的问题(“NSPasteboard线程安全吗?”):Thread Safety Summary中没有具体的答案,但有一般声明:

  

...可变对象通常不是线程安全的。要在线程应用程序中使用可变对象,应用程序必须适当地同步。

我认为NSPasteboard是一个可变对象,所以没有。

实际上,这不是问题:您通常只使用NSPasteboard来响应操作消息(例如,copy:),拖动或服务调用,而这些只发生在无论如何主线程。要让它们在辅助线程上发生,您必须自己从在辅助线程上运行的代码中显式发送此类消息,在这种情况下,您已经做了非常错误的事情。

答案 1 :(得分:0)

猜想:

我认为您的问题与线程无关,但事实上,通过返回YES,您告诉系统数据已准备就绪。您是否尝试将数据移至支持NSPasteboardWritingNSPasteboardReading的自定义类?这样,数据的访问器可以阻塞,直到数据准备就绪。

请参阅Pasteboard Documentation