A smart way to retrieve allowed file types from plist
Asked Answered
B

1

9

Scenario:

I like to define the allowed file types (content types) in the Info.plist file of my Cocoa application. Therefore, I added them like the following example shows.

# Extract from Info.plist
[...]
<key>CFBundleDocumentTypes</key>
<array>
    <dict>
        <key>CFBundleTypeName</key>
        <string>public.png</string>
        <key>CFBundleTypeIconFile</key>
        <string>png.icns</string>
        <key>CFBundleTypeRole</key>
        <string>Viewer</string>
        <key>LSIsAppleDefaultForType</key>
        <true/>
        <key>LSItemContentTypes</key>
        <array>
            <string>public.png</string>
        </array>
    </dict>
[...]

Further, my application allows to open files using an NSOpenPanel. The panel allows to set the allowed file types through the following selector: setAllowedFileTypes:. The documentation states that UTI can be used.

The file type can be a common file extension, or a UTI.


A custom solution:

I wrote the following helper method to extract the UTI from the Info.plist file.

/**
    Returns a collection of uniform type identifiers as defined in the plist file.
    @returns A collection of UTI strings.
 */
+ (NSArray*)uniformTypeIdentifiers {
    static NSArray* contentTypes = nil;
    if (!contentTypes) {
        NSArray* documentTypes = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleDocumentTypes"];
        NSMutableArray* contentTypesCollection = [NSMutableArray arrayWithCapacity:[documentTypes count]];
        for (NSDictionary* documentType in documentTypes) {
            [contentTypesCollection addObjectsFromArray:[documentType objectForKey:@"LSItemContentTypes"]];
        }
        contentTypes = [NSArray arrayWithArray:contentTypesCollection];
        contentTypesCollection = nil;
    }
    return contentTypes;
}

Instead of [NSBundle mainBundle] also CFBundleGetInfoDictionary(CFBundleGetMainBundle()) can be used.


Questions:

  1. Do you know a smarter way to extract the content type information from the Info.plist file? Is there a Cocoa-build-in function?
  2. How do you deal with the definition of folders that can contained there, e.g. public.folder?

Note:
Throughout my research, I found this article quite informative: Simplifying Data Handling with Uniform Type Identifiers.

Bulge answered 27/9, 2011 at 13:8 Comment(0)
T
1

Here is how I read information from a plist (it can be the info.plist or any other plist you have in you project provided you set the correct path)

NSString *resourcePath = [[NSBundle mainBundle] resourcePath];
NSString *fullPath = [NSString stringWithFormat:@"%@/path/to/your/plist/my.plist", resourcePath];
NSData *plistData = [NSData dataWithContentsOfFile:fullPath];
NSDictionary *plistDictionary = [NSPropertyListSerialization propertyListFromData:plistData mutabilityOption:NSPropertyListImmutable format:0 errorDescription:nil];
NSArray *fileTypes = [plistDictionary objectForKey:@"CFBundleDocumentTypes"];
Thickknee answered 5/11, 2011 at 1:11 Comment(3)
I like NSPropertyListSerialization you use. Though, your solution needs to know the path to the plist file. - How about the second part of my question?Bulge
I am not sure I understand the second part of your question if you can clarify it some more I would be happy to try and find a solution for you.Thickknee
As far as I understood you can specify UTIs for individual file types, a group of file types like public.image and for folders public.folder. How do you allow to open images (single/multiple/folder) in your application via file/open and drag-n-drop onto the application icon? Please avoid redundant definitions of UTIs.Bulge

© 2022 - 2024 — McMap. All rights reserved.