Associating file extension with my application

My application uses a text file with an extension of .dssfilelist. On Linux I would register the Mime type and associate it with the application in the .desktop file.

<?xml version="1.0" encoding="UTF-8"?>
<mime-info xmlns="http://www.freedesktop.org/standards/shared-mime-info">
    <mime-type type="text/dssfilelist">
        <comment>DeepSkyStacker file-list file</comment>
        <glob pattern="*.dssfilelist" />
    </mime-type>
</mime-info>

I believe that I need to add stuff to the Info.plist for my application, but I also understand that CFBundleTypeExtensions is deprecated.

So please could you show me what I now need to add to the Info.plist file so that these files will be registered as "text/dssfilelist" type and associated with my application and to associate a .icns file with it?

Here's what filesays:

amonra@Saturn ~ % cd /Applications/DeepSkyStacker.app/Contents/Resources
amonra@Saturn Resources % file DSS_filelist.icns
DSS_filelist.icns: Mac OS X icon, 1291846 bytes, "ic12" type
amonra@Saturn Resources % 

I just noticed something interesting which might suggest my Info.plist isn't incorrect! If I set finder into "View as list" mode, then the .dssfilelist files DO show the correct icon:

However if Finder is set to "View as Icons" then they just show a an Icon that looks like it might be the file contents:

:(

Is that what I should expect to see? I had rather assumed I'd be shown the Icon when using "View as Icons".

David

I had some time to work through this in depth today. As a reminder, my golden rule for this sort of thing is to do what Xcode does. So, I started out by creating a new Xcode project that works. Here’s what I did:

  1. Using Xcode 16.3 on macOS 15.4, I created a new project, named Test783646, from the macOS > Document App template.

  2. That has an asset catalogue, Assets.xcassets, that has an AppIcon placeholder. I filled that out with all the sizes.

  3. At the bottom left of the asset catalogue editor there’s a plus (+) button. I clicked that and chose macOS > macOS Generic Icon.

  4. I named that DocIcon and filled in all the sizes.

  5. I edited the Info.plist file to look like that shown at the end of this post. There’s a bunch of important changes here:

    • I switched from UTImportedTypeDeclarations to UTExportedTypeDeclarations. That’s necessary because I want to define a new file type. The document app template imports public.plain-text and uses that as its file type.

    • I set the content type to be a unique value, com.example.apple-samplecode.Test783646.doc.

    • I conformed that to public.content and public.data, for reasons I explained above.

    • I added .test783646doc as its extension.

    • And DocIcon as its icon.

    • And set the description.

  6. In Test783646Document.swift, I change the exampleText property to be my document type, that is, com.example.apple-samplecode.Test783646.doc.

  7. In the target editor, I changed the deployment target to macOS 15.0.

  8. I built the app.

The app structure now looks like this:

% find Test783646.app 
Test783646.app
Test783646.app/Contents
Test783646.app/Contents/_CodeSignature
Test783646.app/Contents/_CodeSignature/CodeResources
Test783646.app/Contents/MacOS
Test783646.app/Contents/MacOS/Test783646
Test783646.app/Contents/MacOS/__preview.dylib
Test783646.app/Contents/MacOS/Test783646.debug.dylib
Test783646.app/Contents/Resources
Test783646.app/Contents/Resources/AppIcon.icns
Test783646.app/Contents/Resources/Assets.car
Test783646.app/Contents/Info.plist
Test783646.app/Contents/PkgInfo

Xcode has unpacked AppIcon because that’s a strict requirement. It’s left DocIcon in the asset catalogue because that placement is compatible with my deployment target.


I then tested the app:

  1. I restored a macOS 15.3.2 VM to a clean snapshot. Note that there’s nothing special about that version number; it’s just what I have lying around.

  2. I copied the app to the VM using scp.

  3. In the VM, I see that the app has the right icon.

  4. I launched the app and saved a new document to disk. It has the right document icon.


Now, I realise that you don’t want to use an asset catalogue, so I rebuilt the app to use a .icns:

  1. I extract a .iconset from the asset catalogue of the built app:

    % iconutil -c iconset -o DocIcon.iconset Test783646.app/Contents/Resources/Assets.car DocIcon
    

    I could’ve built this .iconset manually, but extracting it was easier (-:

  2. In Xcode, I removed DocIcon from the asset catalogue.

  3. And added the DocIcon.iconset that I created in step 1.

  4. I built the app.

Now the built app looks like this:

% find Test783646.app 
Test783646.app
…
Test783646.app/Contents/Resources/DocIcon.icns
Test783646.app/Contents/Resources/AppIcon.icns
…

And there’s no sign of DocIcon in the asset catalogue:

% assetutil -I Test783646.app/Contents/Resources/Assets.car | grep DocIcon
% 

I then repeated my test process and confirmed that the doc icon still works.

IMPORTANT Note how the test process involves restoring my VM from a fresh snapshot, so I’m 100% sure that my first test run won’t interfere with the second.


So, in summary, in the built app, I have this:

% find Test783646.app 
Test783646.app
…
Test783646.app/Contents/Resources/DocIcon.icns
Test783646.app/Contents/Resources/AppIcon.icns
…
% file Test783646.app/Contents/Resources/DocIcon.icns
Test783646.app/Contents/Resources/DocIcon.icns: Mac OS X icon, 37195 bytes, "ic12" type

and this:

% plutil -p Test783646.app/Contents/Info.plist 
{
  …
  "CFBundleDocumentTypes" => [
    0 => {
      "CFBundleTypeRole" => "Editor"
      "LSHandlerRank" => "Default"
      "LSItemContentTypes" => [
        0 => "com.example.apple-samplecode.Test783646.doc"
      ]
      "NSUbiquitousDocumentUserActivityType" => "com.example.apple-samplecode.Test783646.exampledocument"
    }
  ]
  …
  "UTExportedTypeDeclarations" => [
    0 => {
      "UTTypeConformsTo" => [
        0 => "public.content"
        1 => "public.data"
      ]
      "UTTypeDescription" => "Test783646 document"
      "UTTypeIconFile" => "DocIcon"
      "UTTypeIdentifier" => "com.example.apple-samplecode.Test783646.doc"
      "UTTypeTagSpecification" => {
        "public.filename-extension" => [
          0 => "test783646doc"
        ]
      }
    }
  ]
}

I think this should be enough to get you on track, but let me know otherwise.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
	<key>CFBundleDocumentTypes</key>
	<array>
		<dict>
			<key>CFBundleTypeRole</key>
			<string>Editor</string>
			<key>LSHandlerRank</key>
			<string>Default</string>
			<key>LSItemContentTypes</key>
			<array>
				<string>com.example.apple-samplecode.Test783646.doc</string>
			</array>
			<key>NSUbiquitousDocumentUserActivityType</key>
			<string>$(PRODUCT_BUNDLE_IDENTIFIER).exampledocument</string>
		</dict>
	</array>
	<key>UTExportedTypeDeclarations</key>
	<array>
		<dict>
			<key>UTTypeConformsTo</key>
			<array>
				<string>public.content</string>
				<string>public.data</string>
			</array>
			<key>UTTypeDescription</key>
			<string>Test783646 document</string>
			<key>UTTypeIconFile</key>
			<string>DocIcon</string>
			<key>UTTypeIdentifier</key>
			<string>com.example.apple-samplecode.Test783646.doc</string>
			<key>UTTypeTagSpecification</key>
			<dict>
				<key>public.filename-extension</key>
				<array>
					<string>test783646doc</string>
				</array>
			</dict>
		</dict>
	</array>
</dict>
</plist>

I changed one thing in my Info.plist and now it works as I expected.

I changed this:

			<key>UTTypeConformsTo</key>
			<array>
				<string>public.plain-text</string>

to

			<key>UTTypeConformsTo</key>
			<array>
				<string>public.data</string>

Now the Icon view in Finder shows the Icon I want instead of an icon it builds itself from the content of the text file.

Thanks again for your assistance David

Associating file extension with my application
 
 
Q