How can I make custom icons appear for document types associated with my macOS app in the Finder? - xcode

I have successfully created UTIs and the Finder is able to identify that the files belong to my application and that they are specific types (such as ITC Data File). However, I am unable to make the OS use the custom icons I have specified in my property list file in Xcode.
Here is the relevant portion of my plist file:
<key>CFBundleDocumentTypes</key>
<array>
<dict>
<key>CFBundleTypeExtensions</key>
<array>
<string>itc</string>
<string>vpitc</string>
<string>ITC</string>
</array>
<key>CFBundleTypeIconFile</key>
<string>DataFileBackground</string>
<key>CFBundleTypeIconSystemGenerated</key>
<integer>0</integer>
<key>CFBundleTypeName</key>
<string>ITC Data File</string>
<key>CFBundleTypeRole</key>
<string>Viewer</string>
<key>LSHandlerRank</key>
<string>Default</string>
<key>LSItemContentTypes</key>
<array>
<string>public.itcdatafile</string>
</array>
<key>NSDocumentClass</key>
<string></string>
</dict>
<dict>
<key>CFBundleTypeExtensions</key>
<array>
<string>ftitc</string>
<string>FTITC</string>
</array>
<key>CFBundleTypeIconFile</key>
<string>ProjectFileIcon</string>
<key>CFBundleTypeIconSystemGenerated</key>
<integer>0</integer>
<key>CFBundleTypeName</key>
<string>FT-ITC Project File</string>
<key>CFBundleTypeRole</key>
<string>Viewer</string>
<key>LSHandlerRank</key>
<string>Default</string>
<key>LSItemContentTypes</key>
<array>
<string>public.ftitcproject</string>
</array>
<key>NSDocumentClass</key>
<string></string>
</dict>
</array>
I previously managed to get the Finder to show a custom test icon, but I am unsure how I did it and am unable to reproduce it. The icons are defined in the 'Assets' as 'macOS generic icon':
How can I get custom icons for my associated files? And does the change (if successful) take time for the OS to update?
Thanks.

Issue might have been related to the system cacheing the icons. Right clicking the file and clicking 'view info' resulted in the system updating the icon.
When I update the icon .png file, I also need to do this to get the system to use the new image as icon.

Related

Xcode template for file/folder, Not Project

I tried to create MVVM Template to creating file(s) (not project).
I want to add group (yellow folder) when I create the file, but I can't. When I created it, It create a folder (blue folder).
How can I achieve this?
I tried to use Node and Definitions but it still showing blue folder.
My MVVM.xctemplate hierarchy is like this:
-- (folder) FILEBASENAME FILEBASENAME
---- ___FILEBASENAME___ViewController.swift
--TemplateIcon.png
--TemplateIcon#2x.png
--TemplateInfo.plist
Here is my TemplateInfo.plist file
<?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>Kind</key>
<string>Xcode.IDEFoundation.TextSubstitutionFileTemplateKind</string>
<key>Description</key>
<string>An empty MVVM Swift file.</string>
<key>Summary</key>
<string>An empty Swift MVVM file</string>
<key>AllowedTypes</key>
<array>
<string>public.swift-source</string>
</array>
<key>DefaultCompletionName</key>
<string>File</string>
<key>MainTemplateFile</key>
<string>___FILEBASENAME___.swift</string>
<key>Platforms</key>
<array>
<string>com.apple.platform.iphoneos</string>
</array>
<key>Options</key>
<array>
<dict>
<key>Identifier</key>
<string>productName</string>
<key>Required</key>
<true/>
<key>Name</key>
<string>Name:</string>
<key>Description</key>
<string>The name of the Navigator, ViewController and ViewModel to create</string>
<key>Type</key>
<string>text</string>
<key>Default</key>
<string>MyModel</string>
</dict>
</array>
<key>Definitions</key>
<dict>
<key>___FILEBASENAME___/___FILEBASENAME___ViewController.swift</key>
<dict>
<key>Group</key>
<array>
<string>___FILEBASENAME___</string>
</array>
<key>Path</key>
<string>___FILEBASENAME___/___FILEBASENAME___ViewController.swift</string>
<key>TargetIndices</key>
<array/>
</dict>
</dict>
<key>Nodes</key>
<array>
<string>___FILEBASENAME___/___FILEBASENAME___ViewController.swift</string>
</array>
</dict>
</plist>
Thank you.
Actually, this is not feasible for now. I also faced the same problem and after extensive research, I came to know that giving dynamic names to folders in the custom template is possible but the files inside the folder are not in the app targets and so you can't use them.
For now, after adding a new module I have performed the following steps to overcome this problem
Point to the parent folder, right-click on it, and selects the Add files to option.
A popup will appear, choose the root folder of your module and pick
Create groups and press the Add button.
This will add a custom template inside the project and now we can
safely delete the old folder of our module by right click on it,
selecting Delete, and picking the option Remove reference.
I have posted this answer so developers don't spend much time in research as I have done.

OS X: information about custom URL schemes

Our application makes use of special URIs, e.g. myapp://doSomething. For this purpose the Info.plist file contains following definition:
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleURLName</key>
<string>MyApp handler</string
<key>CFBundleURLSchemes</key>
<array>
<string>myapp</string>
</array>
</dict>
</array>
Now is the problem that a couple of different versions of our application are installed and when clicking a myapp://doSomething-link some "random" version starts (using OS X 10.10.5)).
How can I see what application OS X is trying to launch (the exact path) and how can I get the choice of all applications that support this URL-schema?

How does e.g. TextWrangler generates the preview in finder?

i am almost done with my application. The user is able to edit special files. Now i want to provide a Finder preview but i get stuck.
I watched the apple video about Quick Lock but i am confused.
TextWrangler for example has a scrolable view of the file content. That is what i want for my Documents.
Can you give me a hint how to do this?
My knowledge so far is that i have to write a QuickLock Plugin. The XCode template is wirtten in c, so i suggest i have to use c, not swift.
If I am right two questions:
- How do i get a scrolled view with text content form a file
- How to put the .qlgenerator inside my main project's Contents/Library/.. folder?
Thanks a lot for any help. Two days reading is not always the way to get clear about things.
*** Update **
this is my info.plist CFBundleDocumentTypes
<key>CFBundleDocumentTypes</key>
<array>
<dict>
<key>CFBundleTypeExtensions</key>
<array>
<string>json</string>
</array>
<key>CFBundleTypeIconFile</key>
<string>Icon_512x512#2x</string>
<key>CFBundleTypeName</key>
<string>JSON Document</string>
<key>CFBundleTypeOSTypes</key>
<array>
<string>TEXT</string>
</array>
<key>CFBundleTypeRole</key>
<string>Editor</string>
<key>LSItemContentTypes</key>
<array>
<string>public.json</string>
<string>public.text</string>
<string>public.data</string>
<string>public.item</string>
<string>public.content</string>
</array>
<key>NSDocumentClass</key>
<string>$(PRODUCT_MODULE_NAME).Document</string>
</dict>
</array>
<key>UTExportedTypeDeclarations</key>
<array>
<dict>
<key>UTTypeConformsTo</key>
<array>
<string>public.json</string>
</array>
<key>UTTypeDescription</key>
<string>JSON source file</string>
<key>UTTypeIconFile</key>
<string>Icon_512x512#2x</string>
<key>UTTypeIdentifier</key>
<string>public.json</string>
<key>UTTypeTagSpecification</key>
<dict>
<key>public.filename-extension</key>
<array>
<string>json</string>
</array>
</dict>
</dict>
</array>
<key>UTImportedTypeDeclarations</key>
<array>
<dict>
<key>UTTypeConformsTo</key>
<array>
<string>public.json</string>
</array>
<key>UTTypeDescription</key>
<string>JSON source file</string>
<key>UTTypeIconFile</key>
<string>Icon_512x512#2x</string>
<key>UTTypeIdentifier</key>
<string>public.json</string>
<key>UTTypeTagSpecification</key>
<dict>
<key>public.filename-extension</key>
<array>
<string>json</string>
</array>
</dict>
</dict>
</array>
But this is still the preview without preview text or even an icon:
It appears that your app just works with JSON files. That is, they are not some specialization of JSON files.
Therefore, you should not attempt to export any UTI. You are using a system-defined UTI, and you should not export those. You just import them. (Exporting a UTI means that you are attempting to define the UTI. It's not about what types of files your app can write/save.)
Then, in your LSItemContentTypes array, just list public.json. Your app can't open arbitrary text, data, or content. It can only open JSON data. So, just list that.
Unfortunately, public.json conforms to public.text and not public.plain-text and it seems the system doesn't provide a QuickLook preview for that. So, you don't get for free with your documents.
What you could do is export a new UTI which conforms to both public.json and public.plain-text. Your new UTI should use a different file extension to distinguish it from the system-defined public.json's extension. Then, add a dictionary to CFBundleDocumentTypes with the specifics for your unique document type. That way, your app will still be able to import .json files as well as your custom document type. I would expect that only your custom type would get QuickLook previews.
For example, you'd put this in the UTExportedTypeDeclarations array:
<dict>
<key>UTTypeConformsTo</key>
<array>
<string>public.json</string>
<string>public.plain-text</string>
</array>
<key>UTTypeDescription</key>
<string>Your Document Type Description</string>
<key>UTTypeIconFile</key>
<string>Icon_512x512#2x</string>
<key>UTTypeIdentifier</key>
<string>com.yourcompany.yourapp.yourdocumenttypename</string>
<key>UTTypeTagSpecification</key>
<dict>
<key>public.filename-extension</key>
<array>
<string>yourdocumentextension</string>
</array>
</dict>
</dict>
You'll have to fill in various placeholders that I put in there, since I don't know what good values would be. You would invent a filename extension that makes sense for your app. Likewise, you would invent a UTI based on the reverse domain name of your company, similar to your bundle identifier.
Then, you would add this to the CFBundleDocumentTypes array as the first element:
<dict>
<key>CFBundleTypeExtensions</key>
<array>
<string>yourdocumentextension</string>
</array>
<key>CFBundleTypeIconFile</key>
<string>Icon_512x512#2x</string>
<key>CFBundleTypeName</key>
<string>Your Document Type Description</string>
<key>CFBundleTypeRole</key>
<string>Editor</string>
<key>LSItemContentTypes</key>
<array>
<string>com.yourcompany.yourapp.yourdocumenttypename</string>
</array>
<key>NSDocumentClass</key>
<string>$(PRODUCT_MODULE_NAME).Document</string>
</dict>
Obviously, you'll need to fill in the placeholders again.

CoreData not setting type as XML

I'm having a hard time debugging a problem with my data (CoreData, NSPersistentDocument).
I have a subclass of NSPersistentDocument. I am using NSManagedObject subclasses / standard Core Data models. I'm not doing anything special in NSPersistentDocument or with the NSManagedObject classes. I am merely creating an object (in NSPersistentDocument's subclass):
[NSEntityDescription insertNewObjectForEntityForName:#"ModelName"
inManagedObjectContext:[self managedObjectContext]];
When I attempt to save the document in my app, there is a drop-down for file formats. It includes Binary (default), SQLite, and XML. I save the file as XML. When I try to view it (using less, or even opening in Finder), I find that the file is stored as binary.
Is there something special I need to go to force it to XML?
My understanding based on the documentation from Apple is that in using an NSPersistentDocument subclass, I don't need to do the work of setting up the NSPersistentStore or NSPersistentStoreCoordinator. My understanding is all of this comes for free. Also from what I've read, XML is the default.
The template that Xcode creates for a document based app with Core Data works perfectly for what you're describing. You may need to include a bit more info, but one thing to check would be that the document types in your Info.plist are correct. Below are the out of the box values. There's also a graphical editor in Xcode for this under the Info tab when you have your target selected in the project view.
Try creating a new project with Core Data and Document Based Application checked (Xcode 4.3) and check to see if that works fine. If it does, then something in your configuration has changed to make it binary instead of XML.
<key>CFBundleDocumentTypes</key>
<array>
<dict>
<key>CFBundleTypeExtensions</key>
<array>
<string>binary</string>
</array>
<key>CFBundleTypeMIMETypes</key>
<array>
<string>application/octet-stream</string>
</array>
<key>CFBundleTypeName</key>
<string>Binary</string>
<key>CFBundleTypeRole</key>
<string>Editor</string>
<key>LSTypeIsPackage</key>
<false/>
<key>NSDocumentClass</key>
<string>Document</string>
<key>NSPersistentStoreTypeKey</key>
<string>Binary</string>
</dict>
<dict>
<key>CFBundleTypeExtensions</key>
<array>
<string>sqlite</string>
</array>
<key>CFBundleTypeMIMETypes</key>
<array>
<string>application/octet-stream</string>
</array>
<key>CFBundleTypeName</key>
<string>SQLite</string>
<key>CFBundleTypeRole</key>
<string>Editor</string>
<key>LSTypeIsPackage</key>
<false/>
<key>NSDocumentClass</key>
<string>Document</string>
<key>NSPersistentStoreTypeKey</key>
<string>SQLite</string>
</dict>
<dict>
<key>CFBundleTypeExtensions</key>
<array>
<string>xml</string>
</array>
<key>CFBundleTypeIconFile</key>
<string></string>
<key>CFBundleTypeMIMETypes</key>
<array>
<string>text/xml</string>
</array>
<key>CFBundleTypeName</key>
<string>XML</string>
<key>CFBundleTypeOSTypes</key>
<array>
<string>????</string>
</array>
<key>CFBundleTypeRole</key>
<string>Editor</string>
<key>LSTypeIsPackage</key>
<false/>
<key>NSDocumentClass</key>
<string>Document</string>
<key>NSPersistentStoreTypeKey</key>
<string>XML</string>
</dict>
</array>

Have I used uniform type identifiers correctly?

I'm creating an application for Mac OS X, and I wanted to know whether I've used UTIs properly in the application's .plist file:
<key>UTExportedTypeDeclarations</key>
<array>
<dict>
<key>UTTypeIdentifier</key>
<string>com.petroules.silverlock.database</string>
<key>UTTypeDescription</key>
<string>Silverlock Database File</string>
<key>UTTypeIconFile</key>
<string>app.icns</string>
<key>UTTypeConformsTo</key>
<array>
<string>public.data</string>
</array>
<key>UTTypeTagSpecification</key>
<dict>
<key>com.apple.ostype</key>
<string>SDBX</string>
<key>public.filename-extension</key>
<array>
<string>sdbx</string>
</array>
<key>public.mime-type</key>
<string>application/octet-stream</string>
</dict>
</dict>
</array>
This code appears to work, although double-clicking a .sdbx file in Finder doesn't cause my application to open the file itself... but that might just be my code (something I'll look into later).
Also, the format of my file type is encrypted content encoded in base-64... is application/octet-stream the best MIME type to use for that or is there something else I should use, and could I possibly run into compatibility issues anywhere in the spectrum by using a less common MIME type?
Also, I included the following code:
<key>CFBundleDocumentTypes</key>
<array>
<dict>
<key>CFBundleTypeExtensions</key>
<array>
<string>sdbx</string>
</array>
<key>CFBundleTypeIconFile</key>
<string>app.icns</string>
<key>CFBundleTypeName</key>
<string>com.petroules.silverlock.database</string>
<key>CFBundleTypeRole</key>
<string>Editor</string>
<key>LSItemContentTypes</key>
<array>
<string>com.petroules.silverlock.database</string>
</array>
<key>LSHandlerRank</key>
<string>Owner</string>
</dict>
</array>
Should I include this at all because I have the UTI code above? Is this necessary? What are the differences between the two? I wasn't really able to ascertain that from the documentation. Thanks :)
To find out whether this or your code is at fault, quit your app before double-clicking on the file. If this launches your app but doesn't open the file, then your Info.plist is fine and your problem is in -[[NSApp delegate] application:openFile:]. If the app doesn't launch at all, you can be sure that your Info.plist isn't correct as far as Launch Services is concerned.
You do need both the UTExportedTypeDeclarations and CFBundleDocumentTypes stanzas. The first one tells Launch Services that your custom UTI exists. The second tells it that your app is an editor for that file type.

Resources