Revision control
Copy as Markdown
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
import Foundation
open class AppInfo {
/// Return the main application bundle. If this is called from an extension, the containing app bundle is returned.
public static var applicationBundle: Bundle {
let bundle = Bundle.main
switch bundle.bundleURL.pathExtension {
case "app":
return bundle
case "appex":
// .../Client.app/PlugIns/SendTo.appex
return Bundle(url: bundle.bundleURL.deletingLastPathComponent().deletingLastPathComponent())!
default:
fatalError("Unable to get application Bundle (Bundle.main.bundlePath=\(bundle.bundlePath))")
}
}
public static var bundleIdentifier: String {
return applicationBundle.object(forInfoDictionaryKey: "CFBundleIdentifier") as! String
}
public static var appVersion: String {
return applicationBundle.object(forInfoDictionaryKey: "CFBundleShortVersionString") as! String
}
public static var buildNumber: String {
return applicationBundle.object(forInfoDictionaryKey: String(kCFBundleVersionKey)) as! String
}
/// Return the base bundle identifier.
///
/// This function is smart enough to find out if it is being called from an extension or the main application. In
/// case of the former, it will chop off the extension identifier from the bundle since that is a suffix not part
/// of the *base* bundle identifier.
public static var baseBundleIdentifier: String {
let bundle = Bundle.main
let packageType = bundle.object(forInfoDictionaryKey: "CFBundlePackageType") as! String
let baseBundleIdentifier = bundle.bundleIdentifier!
if packageType == "XPC!" {
let components = baseBundleIdentifier.components(separatedBy: ".")
return components[0..<components.count-1].joined(separator: ".")
}
return baseBundleIdentifier
}
}