Become a MacRumors Supporter for $50/year with no ads, ability to filter front page stories, and private forums.

Senor Cuete

macrumors 6502
Original poster
Nov 9, 2011
431
32
I need to create a UTI to enable copying a custom data type to the pasteboard. In the pasteboard programming guide in the XCode documentation, in the Custom Data section, there are example of the required methods to comply with the NSPasteboardWriting and NSPasteboardReading protocols.

In the sample code they use a defined type - BOOKMARK_UTI. Can anyone tell me which one of the three required keys, UTTypeIdentifier, UTTypeDescription or UTTypeTagSpecification this is?

Also two statements in the code examples won't compile:
Code:
if ([type isEqualToString:(NSString *)kUTTypeURL]) {
       return [url pasteboardPropertyListForType:(NSString *)kUTTypeURL];
   }
   if ([type isEqualToString:NSPasteboardTypeString]) {
       return [NSString stringWithFormat:@"<a href=\"%@\">%@</a>",
   [url absoluteString], title];
   }

The compiler doesn't know what a "url" is. You can change this to "URL" but this won't work either. If you change this to "NSURL" the first statement will compile but the second won't because the type "NSURL" has no method "absolute String.
 
It is the UTTypeIdentifier. (The description of which says: "The UTI for the declared type")

Try dumping the value of kUTTypeURL or any of the other kUTType strings using NSLog or the like. Also, dump the type object to see what it holds. Note what the values are. Note that what you have is the UTI string from the pasteboard, and UTTypeIdentifier is the key for the UTI string.

The description is a sort of human-readable value, and not useful for type checking because of it. The tag specification is mostly a mapping telling Apple how to recognize the type. It isn't the type identifier itself, and so it isn't terribly useful for type checking either, since you can recognize a type from its MIME, its HFS FourCC, or the file extension. You don't want to pass that in raw and expect a developer to check it against all the possibilities.

As for the compiler errors, "url" is a variable you failed to define. The example you refer to in the guide, along with the other guides, are not really meant to be copy/pasted, and are snippets to illustrate a technique. In this example, url looks to be a member variable of the class. They tend to assume you have enough of a working knowledge of the language to adapt the techniques yourself. If you want code that is complete and compiles to start from, look at their Sample Code repository, which should include a pasteboard example to work from, and will also help answer some of the questions you might have.
 
It is the UTTypeIdentifier. (The description of which says: "The UTI for the declared type")

The documentation says to declare the UTTypeIdentifier string in the UTExportedTypeDeclarations as something like "appName.myTypeUTI". In the programming example there is a statement:
Code:
writableTypes = [[NSArray alloc] initWithObjects:BOOKMARK_UTI,
   (NSString *)kUTTypeURL, NSPasteboardTypeString, nil];
The UTTypeIdentifier string in the application's property list is not recognized by the compiler either as "appname.UTI" or "UTI". Is there some trick like typecasting the UTI string to something to get the compiler to recognize it?
 
There's no code generated from the Info.plist. So you can't reference it as if it contained variables. (It's for the OS to figure out if your app handles the UTI without having to launch it and interrogate it via an API)

You need to define a const NSString in your code with "appname.UTI" as well, and then reference that in your code:

Code:
const NSString *myUTI = @"appname.UTI";

Again, I really recommend looking at a proper sample rather than the code snippets. It spells out these implicit things. And if that snippet comes from a complete sample, you will see how BOOKMARK_UTI is defined in a similar way (or using #define).
 
I got it done. A few comments:

The compiler likes
Code:
#define my_UTI @"app.myType_UTI"
better than
Code:
const NSString *my_UTI = @"app.myType_UTI";
In some instances the compiler will complain that the latter discards qualifiers and you will have to cast it to (NSString*) to get rid of the warning. Both of these will work.

Calling the pasteboard method
Code:
BOOL ok = [pb canReadObjectForClasses: classes options: options];
and setting a breakpoint, logging a message or return()ing if ok == NO before reading the object(s) from the pasteboard is useful in debugging.

I added the custom type to the pasteboard using
Code:
BOOL written = [pb setData: date forType: @"app.my_UTI"];
Checking the BOOL is a good idea when you are writing the code and generally one should write a few lines to respond to errors like this having a value of NO anyway.

Also I add images of myDocument to the pasteboard as TIFF and PDF. Would it be useful to post jpeg, BMP, PNG, etc. types as well?

Thanks for your help.
 
Last edited:
Register on MacRumors! This sidebar will go away, and you'll see fewer ads.