Get the main app bundle from within extension

Jordan H picture Jordan H · Oct 4, 2014 · Viewed 9.2k times · Source

Is it possible to get the containing app's NSBundle from within an app extension? I would like to get the main app's display name, not the extension's display name.

Answer

phatblat picture phatblat · Jan 8, 2015

The +mainBundle method returns the bundle containing the "current application executable", which is a subfolder of your app when called from within an extension.

This solution involves peeling off two directory levels from the URL of the bundle, when it ends in "appex".

Objective-C

NSBundle *bundle = [NSBundle mainBundle];
if ([[bundle.bundleURL pathExtension] isEqualToString:@"appex"]) {
    // Peel off two directory levels - MY_APP.app/PlugIns/MY_APP_EXTENSION.appex
    bundle = [NSBundle bundleWithURL:[[bundle.bundleURL URLByDeletingLastPathComponent] URLByDeletingLastPathComponent]];
}

NSString *appDisplayName = [bundle objectForInfoDictionaryKey:@"CFBundleDisplayName"];

Swift 2.2

var bundle = NSBundle.mainBundle()
if bundle.bundleURL.pathExtension == "appex" {
    // Peel off two directory levels - MY_APP.app/PlugIns/MY_APP_EXTENSION.appex
    bundle = NSBundle(URL: bundle.bundleURL.URLByDeletingLastPathComponent!.URLByDeletingLastPathComponent!)!
}

let appDisplayName = bundle.objectForInfoDictionaryKey("CFBundleDisplayName")

Swift 3

var bundle = Bundle.main
if bundle.bundleURL.pathExtension == "appex" {
    // Peel off two directory levels - MY_APP.app/PlugIns/MY_APP_EXTENSION.appex
    let url = bundle.bundleURL.deletingLastPathComponent().deletingLastPathComponent()
    if let otherBundle = Bundle(url: url) {
        bundle = otherBundle
    }
}

let appDisplayName = bundle.object(forInfoDictionaryKey: "CFBundleDisplayName")

This will break if the pathExtension or the directory structure for an iOS extension ever changes.