Adding a custom UTI to a document app

Discussion in 'Mac Programming' started by mdeh, Nov 8, 2009.

  1. mdeh macrumors 6502

    Jan 3, 2009
    #1 questions have had plenty of views, but no answers ....yet :D

    I am still playing around with pasteboards...slowly making progress. I **think** this is easy, but have not been able to find a good example.

    Lets say I have declared a custom UTI in a doc-based application. ...lets call it "com.myCompany.BookMarkUTI".

    **How** exactly do I add it to the plist ( I am assuming that *that* is indeed where it is added). ( And if the answer is to use the plist editor, which category is it added to)?

    Thanks in advance.
  2. mdeh thread starter macrumors 6502

    Jan 3, 2009
    Yes...that helps...almost. I think the issue is not so much that I have not read about it, as more that the concept is not yet entirely clear! :)

    How does this look to you? (This is in the "event class" which contains ivars like date, name, etc.

    Added this to the info.plist...hopefully the image is legible.

    Screen shot 2009-11-08 at 2.09.33 PM.png

    Now, in code, ( all related to pasteboard) this:

    I *hope* that the cast is correct in the define the app crashes, but not sure if it is related to this , yet!

    #define MYUTI (NSString*)"com.testMode.Event_UTI"
    .......other stuff.........
    - (NSArray *)writableTypesForPasteboard: (NSPasteboard *)pasteboard
    	NSArray *typeArray = [NSArray arrayWithObjects: (NSString *)kUTTypeURL, NSPasteboardTypeString, MYUTI, nil];
    	return typeArray;
    - (id)pasteboardPropertyListForType: (NSString *)type
    	if ( [ type isEqual:MYUTI] )
    	return [ NSKeyedArchiver archivedDataWithRootObject:self];

    Now, I am **assuming** ( never smart) that the method

    "- (id)pasteboardPropertyListForType: (NSString *)type"

    is essentially saying, "How do you want me to handle this type?"

  3. chown33 macrumors 604

    Aug 9, 2009
    The best way to see what makes a valid UTI is to open the plist of an app that has valid UTIs.

    You should also look at sample code.
    For example, google the words: uti sample code

    #define MYUTI (NSString*)"com.testMode.Event_UTI"
    I didn't look closely at your code, but that is very wrong. It should be:

    #define MYUTI @"com.testMode.Event_UTI"
  4. mdeh thread starter macrumors 6502

    Jan 3, 2009

    I agree about looking at code....but I had a hard time finding any samples. Your search method helps. As to the string, I assumed, as UTIs are CFStrings, and as I had seen in the documentation, that there is "toll-free" bridging" between and NSString and a CFString, that I needed a caste to use it as an NSString. I had seen this done elsewhere. But, I guess , if one **starts** in an Obj-C environment, one can assume Xcode treats it as an NSString...if that even makes sense.
  5. chown33 macrumors 604

    Aug 9, 2009
    There is toll-free bridging between CFString and NSString*. That's not the problem.

    The problem is that this:

    " to put here"
    is a C string literal. It is not a CFString nor NSString*.

    A C string literal is an array of char with a null terminator. It's not an object, and casting it to NSString* doesn't make it one.
  6. mdeh thread starter macrumors 6502

    Jan 3, 2009
    Hi Chown,
    Well...have done a lot of reading about CFString...I like to understand you can see. So, this from the Apple Docs

    So, ran this little test code.

    #import <Foundation/Foundation.h>
    int main (int argc, const char * argv[]) {
        NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
    	CFStringRef str = CFSTR( "Hello World");
    	NSString *str_2 = (NSString *) str;
    	NSLog(@"\n%@", str_2);
        [pool drain];
        return 0;

    BTW...thanks for all your help.
  7. Sander macrumors 6502

    Apr 24, 2008
    That's not the same thing as was in your original example though. The CFSTR wasn't there, and like chown33 said, you were trying to cast a C string literal to an NSString*. Unfortunately, a cast is a powerful construct which basically tells the compiler "Trust me, I know what I'm doing."

    By the way, in my experience it's best to keep UTIs in all lower case. I found out yesterday that when saving a document in my own file type I received the UTI with the same capitalization as I put it in my .plist, but when loading it, it was all lowercase (so it wasn't recognized by my straight string compare).

    Also of note is that in 10.4, the writeToURL and readFromURL methods on my NSDocument subclass got the "human readable" type name as the typeName parameter, whereas on 10.5 they get the UTI.
  8. mdeh thread starter macrumors 6502

    Jan 3, 2009
    Agreed! The problem is that you are on the **other** side of the learning curve :). I am still trying to figure these things out...and it's a very steep road to hoe. So, if my questions sometimes do not make good sense, it's because I have not quite articulated in my own mind exactly what it is that I do not understand. So, the help received here is invaluable in a) helping to focus on the exact issue ( which more than often is not what was asked in the first place) and b) providing, often , the thread upon which to hang the myriad of facts that one has processed in a somewhat disorderly fashion.

    Will keep that in mind.

    Sander...could you perhaps just give an example of the last issue.

    Thanks in advance. Your input is much appreciated.
  9. Sander macrumors 6502

    Apr 24, 2008
    I am developing an app and wanted to keep compatibilty with 10.4. I assume you know how loading and saving works in a document-based app. I chose to override writeToURL: ofType: error: and readFromURL: ofType: error:. An UTI also has a "human-readable" representation, which you can see in the "Save As..." file types popup menu of your app. For example, it might say "Portable Network Graphics image" instead of "public.png" there.

    In 10.4, the "ofType" parameter would be "Portable Network Graphics image". That's a big nuisance, because I can't map this back onto the real UTI. I had to resort to an ugly hack (looking at the file extension - so Windows!).

    I then compiled for 10.5, and to my surprise, the ofType parameter is now "public.png".

Share This Page