Cocoa Programming for Mac OS X - Aaron Hillegass [94]
The hierarchical nature of UTIs enables an application to be broad (public. image) or specific (public.png) when requesting objects from the pasteboard. The system will work out whether a type is permissable, based on what types it conforms to.
Custom UTIs
At some point, you will want to use the pasteboard for custom, application-specific data. In such cases, you can simply use your own UTI. Custom UTIs should take the form of a reverse DNS name, such as com.bignerdranch. raiseman.person. You would then want to implement NSPasteboardWriting and NSPasteboardReading on your custom object or use NSPasteboardItem as an abstraction layer.
Note that custom UTIs do not need to be exported (using Info.plist) unless they are to be used by other applications. If they are exported, they must conform to public.data.
For the More Curious: Lazy Copying
An application can implement copying to a pasteboard in a lazy manner. For example, imagine a graphics application that copies large images to the pasteboard in several formats: PNG, TIFF, PDF, and so on. You can imagine that copying all these formats onto the pasteboard would be hard on the application and the pasteboard server. Instead, such an application might do a lazy copy. That is, the application will declare all the types that it could put on the pasteboard but will put off copying the data until another application asks for it.
Essentially, the application puts an “IOU” (instead of the data) on the pasteboard and gives an object that will provide the data when they are needed. When another application actually asks for the data, the pasteboard server calls back for the data.
You will use an NSPasteboardItem to create this IOU object:
NSPasteboard *pboard = [NSPasteboard generalPasteboard];
[pboard clearContents];
NSPasteboardItem *item = [[NSPasteboardItem alloc] init];
[item setDataProvider:self forTypes:...];
[pboard writeObjects:[NSArray arrayWithObject:item]];
Then implement pasteboard:item:provideDataForType::
- (void)pasteboard:(NSPasteboard *)pasteboard
item:(NSPasteboardItem *)item
provideDataForType:(NSString *)type
{
[item setData:... forType:type];
}
When another application needs the data, this method will be called. At that point, the application must copy the data it promised to the supplied pasteboard item.
As you can imagine, a problem would arise if the pasteboard server asked for the data after the application had terminated. When the application is terminating, if it has an “IOU” currently on the pasteboard, it will be asked to supply all the data promised before terminating. Thus, it is not uncommon for an “IOU” data provider to be sent pasteboard:item:provideDataForType: several times while the application is in the process of terminating.
The trickiest part of a lazy copy is that when the user copies data to the pasteboard and later pastes it into another application, he or she doesn’t want the most recent state of the data. Rather, the user wants it the way it was when he or she copied it. When implementing a lazy copy, most developers will take some sort of a snapshot of the information when declaring the types. When providing the data, the developer will copy the snapshot, instead of the current state, onto the pasteboard.
Of course, when the user does a copy somewhere else, your object will no longer be responsible for keeping the snapshot.
- (void)pasteboardFinishedWithDataProvider:(NSPasteboard *)sender;
If you implement this method, it will be called when you are no longer responsible for keeping the snapshot.
Challenge 1
You are putting the string onto the pasteboard. Create the PDF for the