http://example.com/apps/mycoolapp/icon
, where a web application is returning the image data dynamically, so I can't use the extension from the filename part of the URL.I could just save the image data in a file named "icon" with no extension, since the
UIImage
class will look at the header in the image data to determine the true image type. Neither the filename extension nor the mime type in the Content-Type
response header is reliable in general, but in this case I wrote the web application that my iPhone app is talking to, so I can make sure the Content-Type
in the response is reliable.So now all I need is a way to turn a mime type into a file extension. Rather than build my own table that maps mime types to extensions, I though there might be a way to get this from iOS. Turns out there is: Uniform Type Identifiers, which are available on both iOS and Mac OS X. On iOS, first add the MobileCoreServices framework to your project, then import the
<MobileCoreServices/MobileCoreServices.h>
header. On Mac OS X, add the CoreServices framework and import <CoreServices/CoreServices.h>
A Uniform Type Identifier (UTI) is simply a string like
public.png
or com.apple.pict
that identifies a file or directory type. Proprietary formats use a reverse DNS naming scheme while common formats begin with public
. Additionally, third party developers can define UTIs for their application data formats. UTIs are typically associated with one or more file extensions and mime types. In UTI parlance, extensions and mime types are "tags".If you have a mime type, you can get the UTI for it using the
UTTypeCreatePreferredIdentifierForTag()
function. To get the UTI for image/png
:// get a UTI for a mime type CFStringRef mimeType = (CFStringRef)@"image/png"; CFStringRef uti = UTTypeCreatePreferredIdentifierForTag(kUTTagClassMIMEType, mimeType, NULL); // uti now equals "public.png"Since this is a procedural API, Core Foundation memory management rules are in effect. You are the owner of the
CFStringRef
returned by UTTypeCreatePreferredIdentifierForTag()
and are responsible for calling CFRelease()
on it. Alternately, since CFStringRef
is toll-free bridged to NSString
, you can cast the returned CFStringRef
to a NSString*
and call the -release
or -autorelease
method.Once you have the UTI, you can get the extension for it. The
UTTypeCopyPreferredTagWithClass()
function takes a UTI and returns the first "tag" of the desired class (extension or mime type):// get an extension for a UTI CFStringRef extension = UTTypeCopyPreferredTagWithClass(uti, kUTTagClassFilenameExtension);As with
UTTypeCreatePreferredIdentifierForTag()
, you own the CFStringRef
returned by UTTypeCopyPreferredTagWithClass()
and must CFRelease()
it or cast it to NSString*
and -release
or -autorelease
it.You can easily reverse this process by switching the tag class constants
kUTTagClassMIMEType
and kUTTagClassFilenameExtension
in the examples. There's a little bit more to UTIs than I've covered here. The Uniform Type Identifiers Overview explains all the concepts behind UTIs and tags. The UTType Reference details all the functions and constants. Finally, Uniform Type Identifiers Reference lists all the system defined UTIs and their associated tags.
1 comment:
Thanks for that - especially the "" part - the Apple documentation is wrong on which include file to use, leading to a "expected declaration specifiers or '...' before 'CFXMLTreeRef'" error. Changing the include to fixed the problem.
Post a Comment