Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do you get the Bundle Identifier from an application's name in Cocoa?

Tags:

cocoa

nsbundle

Say you have the name of an application, Mail.app, how do you programmatically obtain com.apple.mail from the application name?

like image 652
Tony Avatar asked Feb 23 '12 06:02

Tony


People also ask

What is a bundle identifier?

A bundle ID or bundle identifier is a unique identifier of an app in Apple's ecosystem. It means that no two apps can have the same bundle ID. A bundle identifier lets macOS recognize any updates to your app. It is used in validating the application signature.

What can I use as a bundle identifier?

A bundle ID or bundle identifier uniquely identifies an application in Apple's ecosystem. This means that no two applications can have the same bundle identifier. To avoid conflicts, Apple encourages developers to use reverse domain name notation for choosing an application's bundle identifier.


2 Answers

The following method will return an application's Bundle Identifier for a named application:

- (NSString *) bundleIdentifierForApplicationName:(NSString *)appName
{
    NSWorkspace * workspace = [NSWorkspace sharedWorkspace];
    NSString * appPath = [workspace fullPathForApplication:appName];
    if (appPath) {
        NSBundle * appBundle = [NSBundle bundleWithPath:appPath];
        return [appBundle bundleIdentifier];
    }
    return nil; 
}

For Mail you can call the method like so:

NSString * appID = [self bundleIdentifierForApplicationName:@"Mail"];

appID now contains com.apple.mail

Swift 5.1

import AppKit

func bundleIdentifier(forAppName appName: String) -> String? {

    let workspace = NSWorkspace.shared
    let appPath = workspace.fullPath(forApplication: appName)
    if let appPath = appPath {
        let appBundle = Bundle(path: appPath)
        return appBundle?.bundleIdentifier
    }
    return nil
}

// For Mail you can call the method like so:

let appID = bundleIdentifier(forAppName: "Mail")

Deprecation

The fullPathForApplication: / fullPath(forApplication:) method has been deprecated in macOS 10.15 - it is unclear what the answer is going forward.

like image 181
David Kennedy of Zenopolis Avatar answered Oct 02 '22 20:10

David Kennedy of Zenopolis


Expanding on Francesco Germinara's answer in Swift 4, macOS 10.13.2:

extension Bundle {
    class func bundleIDFor(appNamed appName: String) -> String? {
        if let appPath = NSWorkspace.shared.fullPath(forApplication: appName) {
            if let itsBundle = Bundle(path: appPath) { // < in my build this condition fails if we're looking for the ID of the app we're running...
                if let itsID = itsBundle.bundleIdentifier {
                    return itsID
                }
            } else {
                //Attempt to get the current running app.
                //This is probably too simplistic a catch for every single possibility
                if let ownID =  Bundle.main.bundleIdentifier {
                    return ownID
                }
            }
        }
        return nil
    }
}

Placing it your Swift project, you can call it like this:

let id = Bundle.bundleIDFor(appNamed: "Mail.app")

or

let id = Bundle.bundleIDFor(appNamed: "Mail")
like image 32
Todd Avatar answered Oct 02 '22 21:10

Todd