Creating NSDocument using Folder Bundles and UTI Identifiers
I've been working on a Lion NSDocument-based application that deals with multiple data files. I decided to work with the NSFileWrapper and treat a folder like a single file. (i.e. Xcode Project Files .xcodeproj) I wanted to get an icon to display for the folder and to have it appear as a single file on Finder. In the NSDocument you need to implement the two save/load methods to get started and then you need to edit your Info.plist file.
- (NSFileWrapper *)fileWrapperOfType:(NSString *)typeName
error:(NSError *__autoreleasing *)outError {
// Save data here ...
}
- (BOOL)readFromFileWrapper:(NSFileWrapper *)fileWrapper
ofType:(NSString *)typeName
error:(NSError *__autoreleasing *)outError {
// Load data here ...
}
Problems
There's a few gotchas with the .plist file. In order to create a NSDocument using Folder Bundles you'll need to set the UTI Identifier for the Document Type and the Exported/Imported UTIs. You'll find this setting on the Info page for your Xcode Target.
- My App doesn't load saved bundles (NSFileWrapper), instead it just looks inside the folder.
- I tried to undo the Export UTI by deleting it and remove the Identifier, but that doesn't help.
- By deleting the Identifier I can't load "New documents".
Solutions
There are two solutions, the second one is more robust, but the first will get you back to when it was working.
Solution 1: Revert back to Xcode template defaults
- Remove all Exported UTIs
- Open your App .plist file and remove the LSItemContentTypes from your App .plist file. You can't see it in the Target -> Info page.
- NOTE: if you don't delete an empty LSItemContentTypes array, then you won't be able to open New files.
- If LSITemContentTypes is defined, it'll ignore the "Bundle" checkbox (LSTypeIsPackage) See the Apple docs.
- Make sure "Bundle" is checked on the Document Types on your Target's Info page, or (LSTypeIsPackage on .plist file)
- This option is magic and auto generates a Identifier for you. (check your save file with "mdls" on the Terminal)
- Don't use an Identifier if you check the Bundle option (Document is distributed as a bundle)
- Clean the Xcode project
Solution 2: Use the package UTI
You'll need to add the correct LSItemContentTypes found in Apple's documentation. I took a look at the Xcode project file with the Terminal utility "mdls" (See sample output below)
- Set a unique identifier (Reverse DNS name) com.Your_Company_Name.Project_Name
- It needs to match theDocument Type and Exported UTIs
- For a bundle, you'll need to set the "Conforms To" for the Exported UTIs to "com.apple.package"
- Apple Docs: "A package (that is, a directory presented to the user as a file)"
- I noticed Xcode project files also include, public.composite-content
- Apple Docs: "Base type for mixed content. For example, a PDF file contains both text and special formatting data"
- NOTE: If you mistype com.apple.package, or leave it out, your file folder will be treated like a public.folder, and you'll get folder behavior.
- Clean the Xcode project
Working Icon and Bundle File
If all goes well you'll now see the Icon (icns) file that you created in the Open dialog and the folder will appear to be a bundle.
Using MDLS to inspect your files
The only way it works as a bundle is if the "com.apple.package" ContentType is listed, otherwise something is wrong. Check your save files with the "mdls" command.
mdls MathAndArt.xcodeproj/