Is NSPasteboard thread safe?
Is it safe to write data to an NSPasteboard object from a background thread? I can't seem to find a definitive answer. I think the assumption is that the data will be written to the filing cabinet before the drag starts.
Background:
I have an app that pulls data from Evernote. When the app is first loaded, it receives the metadata for each note, but not the content of the note. Then the notes of the note are displayed in a diagram. When the user starts dragging the note, the notes are pushed to a background thread, which handles retrieving the note's content from Evernote. Having a main thread block until the data gets results in significant latency and poor user experience, so I return the [outlineView:writeItems:toPasteboard:]
return functionYES
while the background thread processes the data and calls the main thread to write data to the cardboard object. If the content of the note is passed before the user deletes the note somewhere, everything works fine. If the user writes a note somewhere before the data is processed ... well, everything is blocked forever. Is it safe to just use a background thread to write data to cardboard?
a source to share
You can promise data in a filing cabinet without actually having data.
One way is to declare the data type on the filing cabinet, transfer yourself as the owner of the cardboard, and respond with a messagepasteboard:provideDataForType:
by providing the data (blocking if necessary until data arrives or arrives). This means that you will need to remember which objects were copied (for example, by copying them to an array) so that you can retrieve / generate data from them when the promise comes.
Another way referred to in Harald Scheirich's answer is to make your model objects conform to the NSPasteboardWriting protocol , ideally in a category (separate interface independent logic from Mac specific logic). It's much cleaner than the old one, but requires Mac OS X 10.6 and later.
With NSPasteboardWriting, you implement promises by having model objects with a writingOptionsForType:pasteboard:
method return parameterNSPasteboardWritingPromised
. Their method returns data or at least tries as before, this method should block until data arrives or passes to arrive. pasteboardPropertyListForType:
Oh, and to answer the question in the title ("Is NSPasteboard thread safe?"): There is no specific answer in the Thread Safety Overview , but there is this general statement:
... mutable objects are usually not thread safe. In order to use mutable objects in a streaming application, the application must synchronize appropriately.
I would consider NSPasteboard as a mutable object, so no.
In practice, this is not a problem: you usually only work with the NSPasteboard in response to an action message (for example copy:
), a drag and drop, or a service call, and it all only happens on the main thread one way or another. For them to happen on the secondary thread, you will have to explicitly send such messages from the code running on the secondary thread, in which case you are already doing something very wrong.
a source to share
Hypothesis:
I think your problem has nothing to do with threads, but the fact that by returning YES
, you told the system that the data is ready. have you tried to move your data to a custom class that supports NSPasteboardWriting
and NSPasteboardReading
? thus, access to your data may be blocked until the data is ready.
a source to share