Where did the icon come from? - cocoa

Is there a unix tool to which I can pass a file and have it tell me where the icon for the file is coming from?
What I am looking for is something like this:
$WhoProvidedIcon /Path/To/file.myex
UTI: com.myapplication.document
PLIST: /path/to/myapplication.app/Contents/Info.plist
ICON: /path/to/myapplication.app/Contents/Resources/BaseDoc.icns

Icons for most applications on Mac OSX are stored within the app bundle themselves. If you right click on the .app and then select Show Package Contents then go to Contents -> Resources you should see the icon in there.

There are at least three different place from which the OS will provide the icon.
In one situation, NSWorkspace can be used to help identify the location:
NSString* uti = [ws typeOfFile:#"/Users/egorr/Desktop/file.vwx" error:&error];
NSLog( #"UTI: %#", uti );
NSLog( #"UTI localized description: %#", [ws localizedDescriptionForType:uti] );
NSLog( #"UTI error description: %#",[error localizedDescription] );
NSURL* utiDeclarationURL = (NSURL*)UTTypeCopyDeclaringBundleURL( (CFStringRef)uti );
NSLog( #"UTI declaration URL: %#", utiDeclarationURL );
NSDictionary* utiDeclaration = (NSDictionary*)UTTypeCopyDeclaration( (CFStringRef)uti );
NSLog( #"UTI declaration: %#", utiDeclaration );
This won't quite get the path to the icon, but it will get one the application from which the declaration came for the UTI.
An icon might also be supplied from a Quick Look plugin and output from qlmanage can be used to determine if this is the case.
A user can, in Finder's Get Info window, set the application they prefer for all files of a given "type". One can set text file types to always open in TextMate, for example. TextMate the app provides custom file icons for all the file types it can save in. After making this change in Finder's get info windows, all files of that type will have an icon that has been provided by TextMate and registered with a UTI. To determine whether this is the case, one would need to look at the launch services database - lsregister -dump

I don't know of any specific tools that provide this information. However, it sounds like you have overlapping extensions. If Finder.app is showing an icon for a file then you should be able to just look in the info window for the file and see what application is listed to open the document by default. Then look at the .plist file for that application to see if it is using your extension. The info window should also say what kind of document it is which could be useful if the application that is supplying the icon has been deleted, or otherwise not listed as the default application.

Related

macOS - Get path to currently running application

Question
Is it possible to determine the location a macOS app was launched from at runtime?
Context
I develop a Safari Extension, and in order for the extension to be enabled the application needs to be present /Applications/. Several users have tried to run the application directly from the DMG file and then complained that the extension doesn't appear in Safari's extension settings. I would like to detect this and alert them that they need to move the file.
You can use NSBundle, specifically the bundlePath property. The documentation says:
The full pathname of the receiver’s bundle directory.
And you can use it something like this:
NSString* bundlePath;
bundlePath = [[NSBundle mainBundle] bundlePath]
NSLog(#"%#", bundlePath);
There's also bundleURL if you want a NSURL to work with instead of a string.

Where is my database located of my MacOS app?

What is the database location of a MacOS application when using Core Data ?
I searched everywhere on my Mac and did't find it.
I Have the hidden files OFF and I'm sure there is data in my database.
Also I don't use app Sandbox.
If you have sandboxing enabled for your app, it will be placed under ~/Library/Containers/app.bundle.id/Data/Library/Application Support/AppTargetName where app.bundle.id is the Bundle Identifier specified in your app's target and AppTargetName is the name of that target, i.e. the name of the generated .app file. In that folder you should find the SQLite files that contain the database data.
Look for the persistentStoreCoordinator method in your AppDelegate.m. There is a line
NSURL *applicationDocumentsDirectory = [self applicationDocumentsDirectory];
Just add
NSLog(#"myDirectory: %#", applicationDocumentsDirectory);
This assumes you started your project with Xcode 8 Cocoa template with "use Core Data" option.
Or add
NSLog(#"Array of CD stores: %#", self.persistentStoreCoordinator.persistentStores);
to applicationDidFinishLaunching, for example. The resulting path should be in your user's library Users/<user>/Library/Application Support/<whatever>/<appname>.storedata.
Ask your NSPersistentStoreCoordinator.

Quickly find the full path to an app whose name contains a specific phrase

I'm working on a little app that acts as a plugin for a 3rd party app. For it to function, I need to access a saved file from the 3rd party app ("other app" from here). In newer versions, the other app keeps this in ~/Application Support/Test App/Saved Files/.
This is easy to go to, using something like this:
NSString *savedFiles = [NSHomeDirectory() stringByAppendingPathComponent:#"~/Application Support/Test App/Saved Files"];
But I also want to make it compatible with older versions, and they don't use the application support folder. Older versions went in their folder in the user's applications folder, for example this structure:
~/Applications/Test App/Test App.app
~/Applications/Test App/Saved Files/
I can use the same as above to find the location to saved files. But the app won't always be installed here, or the folder name could be different in a different language. This is the problem.
I thought so far, I thought the following are options to get the path:
Ask the user to navigate to the file with a file selector from
within my app.
Ask the user where the "Test App.app" is, and get the
path via "../Saved Files/" relative to that.
Can the app get the path to a previously run application via the system?
Can the app use spotlight to quickly find the location?
Are there other ways to do this automatically, reliably, and quickly?
1 and 2 are not preferred, as that would require the user to "work" to give the app the path. What do you all think?
Are there other ways to automate this?
Which would be the fastest?
You can try to ask LaunchServices for the app's location, given its bundle identifier with the LSFindApplicationForInfo call:
CFURLRef urlRef = NULL;
LSFindApplicationForInfo(kLSUnknownCreator, (CFStringRef)#"com.example.some-app", NULL, NULL, &urlRef);
NSLog(#"URL: %#", (__bridge id)urlRef);
This assumes that the bundle identifier is the same between the two variants you mention. If it's really just the name that is the same, you could query by name instead:
CFURLRef urlRef = NULL;
LSFindApplicationForInfo(kLSUnknownCreator, NULL, (CFStringRef)#"Test App.app", NULL, &urlRef);
NSLog(#"URL: %#", (__bridge id)urlRef);

How to register a custom non-document UTI / file type for OSX to recognize it?

I've read all the tickets about this issue, but I still don't get it right. I have a non-document OSX app (for OSX Lion and MountainLion). I want this app to export and import custom data, associated with a custom file extension ".iobs". Internally, these files are just data archived with [NSKeyedArchiver archivedDataWithRootObject:], and saved onto the disk with the "iobs" extension.
So, my check list is this:
1) Export mechanism: checked. My app create correctly .iobs files. If I run "file <filename.iobs>" in the Terminal, I get "iObserve_exportedItems.iobs: Apple binary property list"
2) Declaration of an exported UTI, checked. As shown in the image below. I did NOT declared a custom Document type, since it I never use NSDocument inside my app, and there is no point. Anyway, I already tried and failed. I've tried also different combinations of "Conforms To" entries, but with no success.
3) Is there any 3rd point??? Do I need to start my app once to let the system know? I just ran it in Debug from Xcode so far, and this has no effect. So I guess my Info.plist is wrong, but I filled it from within Xcode4 interface, so???
Thanks for any help, hint, question, suggestion.
Ok, so apparently, I do have to declare a document type even if I don't specify a document class. See the attached screenshot. Note that leaving only the Document UTI doesn't work. I do need the two (exported UTI and document type). Note also that if I say it conforms to com.apple.binary-property-list, I don't have the right icon.
And for those who wonder, there is nothing to do to "register" a type (and its subsequent changes) apart from launching the app once.

Dropping Files onto Dock Icon in Cocoa

How can I drop a file(or select to open it in Finder) of a type specified in the Info.plist onto my dock icon and then calling a method with the full path of the file?
If you've set up your Info.plist's CFBundleDocumentTypes array properly (either 'LSItemContentTypes' or 'CFBundleTypeExtensions'), then you just need to set up an NSApplication delegate and implement the delegate method, application:openFile:.
If you're expecting multiple files to be dropped at once, implement application:openFiles:.
For promised files (NSFilesPromisePboardType/kPasteboardTypeFileURLPromise) see Dropping promised files on to application icon in Dock.
Here's an updated solution for Xcode 5.
In AppDelegate.m
-(BOOL)application:(NSApplication *)sender openFile:(NSString *)filename
{
NSLog(#"%#", filename);
return YES;
}
And in Xcode setup Document Types under Project > Targets > Info:
Check settings in Info.plist in case you have an empty 'Document Content Type UTIs' array which should be filled out properly or else deleted.
Your Info.plist should look something like this:
On current systems you can use a UTI instead of the old-style four-char types (such as fold above). In Xcode's document type editor, make a new type with:
Name: Folder
Identifier: public.folder
public.folder is a subtype of public.directory. public.folder matches directories that appear as such to the user, i.e. not packages like .app wrappers.
Select your application in the target group of the side pane and use get info. Then in the new window select the properties tab to add a new document type. Name it "Folder" for convenience and the OS Types needs to be "fold"; the store type and role you can leave as is.
If you're actually making a document-based app, setting it up to give you the path will have you doing far more work than you need to. Simply use the document-based application template. The document controller will create an instance of the right class for you; you need only write that class.
An application you create this way will handle file drops (by opening them as documents) for free.

Resources