Get the main app bundle from within extension Get the main app bundle from within extension ios ios

Get the main app bundle from within extension


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.mainif 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.


Building upon @phatblat's answer, here is a solution which is less likely to break from file structure changes.

extension Bundle {    /// Return the main bundle when in the app or an app extension.    static var app: Bundle {        var components = main.bundleURL.path.split(separator: "/")        var bundle: Bundle?        if let index = components.lastIndex(where: { $0.hasSuffix(".app") }) {            components.removeLast((components.count - 1) - index)            bundle = Bundle(path: components.joined(separator: "/"))        }        return bundle ?? main    }}