Cocoa Snippet: Finding a File’s ‘Kind’

January 7, 2007 at 5:46 pm 6 comments

+ (NSString *)humanReadableFileType:(NSString *)path
{
NSString *kind = nil;
NSURL *url = [NSURL fileURLWithPath:[path stringByExpandingTildeInPath]];
LSCopyKindStringForURL((CFURLRef)url, (CFStringRef *)&kind);
return kind ? [kind autorelease] : @""; // If kind happens to be an empty string, don't autorelease it
}

Thanks very much to Peter Hosey and David Phillip Oster for being unbelievably helpful in clearing up the labyrinth that is CSStringRef to NSString usage.

Entry filed under: cocoa, code, snippets. Tags: .

Right Tool, Right Job (?) Why I Dig Objective-C

6 Comments

  • 1. Peter Hosey  |  January 7, 2007 at 10:14 pm

    Don’t forget to release what you have copied. In CF, you own a reference to any object that you Create, Copy, or Retain, and you must release that reference accordingly. (For comparison, the rule in Foundation is copy, alloc, retain, or new.)

    The easiest way would be to autorelease it. Thanks to toll-free bridging, autorelease works just fine for CF-obtained objects (the autorelease pool will send the object -release, which is equivalent to CFRelease).

    Don’t forget to *not* autorelease your empty string, though (since it already has a net retain count of 0). The easiest way would be something like this:

    LSCopyKindStringForURL(…, &kind);
    if(kind) kind = [kind autorelease];
    else kind = @””;
    return kind;

    Or, if you’re OK with the ?: operator:
    LSCopyKindStringForURL(…, &kind);
    return kind
    ? [kind autorelease]
    : @””;

  • 2. David Phillip Oster  |  January 12, 2007 at 5:40 am

    Your example is wrong. You must write it this way:
    + (NSString *)humanReadableFileType:(NSString *)path{
    NSString *kind = nil;
    NSURL *url = [NSURL fileURLWithPath:[path stringByExpandingTildeInPath]];
    LSCopyKindStringForURL((CFURLRef)url, (CFStringRef *)&kind);
    return kind ? [kind autorelease] : @””;
    }

    That way, you get the toll-free bridging from CSStringRef to NSString, and you either return the autoreleased copy, or nil.

    My point is that the line:

    NSString *kind = [NSString string];

    is wrong, since one of two things will happen:
    (a) LSCopyKindStringForURL() will ignore the previous value of ‘kind’ and store over it with its own value, a copy that must be autoreleased.
    or
    (b) LSCopyKindStringForURL() will hit an error executing, and potentially do nothing.

    in case (a), you must autorelease the result, in case (b) you must not autorelease the result. So the only reasonable initial value for kind is nil, since [nil autorelease] is harmless to execute.

  • 3. David Phillip Oster  |  January 14, 2007 at 1:10 am

    I was overly sharp in my previous comment. I apologize for my tone.

    [NSString string] returns an autoreleased object. If you autorelease it again, you’ve set up a double-delete when the pool is drained.

    #import

    #if DEBUG // debug builds only
    NSDebugEnabled = YES;
    NSZombieEnabled = YES;
    #endif

    will cause the runtime system to get your attention if you do a double delete.

  • 4. David Phillip Oster  |  January 14, 2007 at 1:10 am

    should be:
    #import <NSDebug,h>

  • 5. Patrick  |  January 14, 2007 at 1:18 am

    Thank you very much, David. I truly appreciate – and am rather startled – that people read my blog and are passionate enough to correct me when I make errors.

    Do you have a blog?

  • 6. David Phillip Oster  |  January 15, 2007 at 8:39 am

    I’m glad you asked, since this gives me an opportunity to paste, out of working code:

    #import <Foundation/NSDebug.h>
    #if DEBUG
      NSDebugEnabled = YES;
      NSZombieEnabled = YES;
    #endif

    No, I don’t yet have a blog, just 9,600 hits on
    http://groups.google.com/groups/search?q=%22david+phillip+oster%22&start=0&scoring=d


About Me



I'm Patrick Thomson. This was a blog about computer programming and computer science that I wrote in high school and college. I have since disavowed many of the views expressed on this site, but I'm keeping it around out of fondness.

If you like this, you might want to check out my Twitter or Tumblr, both of which are occasionally about code.

Blog Stats

  • 649,966 hits

%d bloggers like this: