从扩展程序中获取主应用程序包

时间:2014-10-04 02:34:21

标签: ios swift nsbundle ios-app-extension

是否可以从应用扩展程序中获取包含应用的NSBundle?我想获取主应用程序的显示名称,而不是扩展程序的显示名称。

2 个答案:

答案 0 :(得分:37)

+mainBundle方法返回包含“当前应用程序可执行文件”的包,该文件夹是从扩展程序中调用时应用程序的子文件夹。

此解决方案涉及从捆绑包的URL中剥离两个目录级别,当它以“appex”结束时。

<强>目标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")

如果iOS扩展的pathExtension或目录结构发生变化,这将会中断。

答案 1 :(得分:1)

以@phatblat的答案为基础,这是一个不太可能因文件结构更改而中断的解决方案。

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
    }
}