在 Swift 中获取应用程序名称

问题描述 投票:0回答:19

如何在 Swift 中获取应用程序名称?

谷歌搜索给了我这个:

[[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleName"];

我将其转换为 Swift;错误 - 方法不存在:

NSBundle.mainBundle().infoDictionary.objectForKey("CFBundleName")
cocoa swift
19个回答
156
投票

这应该有效:

NSBundle.mainBundle().infoDictionary!["CFBundleName"] as! String

infoDictionary
被声明为
var infoDictionary: [NSObject : AnyObject]!
,因此您必须解开它,将其作为 Swift 字典访问(而不是使用
objectForKey
),并且,由于结果是
AnyObject
,因此将其转换。

更新 Swift 3(Xcode 8 beta 2)

尽可能使用常量(和可选值)也总是更好:

Bundle.main.infoDictionary?[kCFBundleNameKey as String] as? String

69
投票

我相信这个解决方案更加优雅。更重要的是,使用

object(forInfoDictionaryKey:)
是 Apple 鼓励的:

“与其他访问方法相比,使用此方法是首选,因为当键可用时,它会返回键的本地化值。”

extension Bundle { var displayName: String? { return object(forInfoDictionaryKey: "CFBundleDisplayName") as? String } }

访问捆绑包显示名称:

if let displayName = Bundle.main.displayName { print(displayName) }
    

61
投票
我创建了一个简单的扩展来获取主屏幕图标下显示的应用程序名称。

默认情况下,应用程序仅设置

CFBundleName

。但是,某些应用程序设置 
CFBundleDisplayName
 
(捆绑包的用户可见名称) 来更改应用程序图标下的标题。添加空格是经常发生的情况,例如捆绑包名称“ExampleApp”可以将捆绑包显示名称设置为“示例应用程序”。

extension Bundle { /// Application name shown under the application icon. var applicationName: String? { object(forInfoDictionaryKey: "CFBundleDisplayName") as? String ?? object(forInfoDictionaryKey: "CFBundleName") as? String } }
用途:

let appName = Bundle.main.applicationName
    

24
投票

Swift 4.2中的答案相同

extension Bundle { class var applicationName: String { if let displayName: String = Bundle.main.infoDictionary?["CFBundleDisplayName"] as? String { return displayName } else if let name: String = Bundle.main.infoDictionary?["CFBundleName"] as? String { return name } return "No Name Found" } }
你可以像下面这样使用它

Bundle.applicationName
或者,另一种方法是避免静态或类方法或属性,而是添加到实例级别。

extension Bundle { var applicationName: String { if let displayName: String = self.infoDictionary?["CFBundleDisplayName"] as? String { return displayName } else if let name: String = self.infoDictionary?["CFBundleName"] as? String { return name } return "No Name Found" } }
以及以下所有内容

Bundle.main.applicationName
希望这有帮助:)


13
投票

斯威夫特4

let appName = Bundle.main.object(forInfoDictionaryKey: "CFBundleDisplayName") as! String


    


7
投票
// 返回应用程序名称

public static var appDisplayName: String? { if let bundleDisplayName = Bundle.main.object(forInfoDictionaryKey: "CFBundleDisplayName") as? String { return bundleDisplayName } else if let bundleName = Bundle.main.object(forInfoDictionaryKey: "CFBundleName") as? String { return bundleName } return nil }
    

6
投票
简单的方法:

let appName = NSBundle.mainBundle().infoDictionary?[kCFBundleNameKey as String] as? String

便捷方式:

extension NSBundle { class func mainInfoDictionary(key: CFString) -> String? { return self.mainBundle().infoDictionary?[key as String] as? String } } print(NSBundle.mainInfoDictionary(kCFBundleNameKey))

kCFBundleNameKey – 标准 Info.plist 键,请参阅CFBundle了解更多信息


6
投票
  1. 所有只返回

    CFBundleName

     的答案通常不会返回用户期望的名称,就好像捆绑包有一个 
    CFBundleDisplayName
    ,然后 Finder、系统框架和大多数其他应用程序都会显示此键。

  2. 大多数答案只是直接访问信息字典,但信息字典可以通过字符串文件进行本地化,当直接访问它们时,这种本地化也会被忽略,因此可能会再次返回错误的名称,因为 Finder 将显示本地化的名称。

  3. 虽然

    CFBundleDisplayName

    Info.plist
     文件中是可选的,但 
    CFBundleName
     实际上不是,但如果您忘记添加它,系统中不会出现任何问题,因此您的信息字典已损坏,但大多数用户可能会永远不会注意到,在这种情况下,大多数答案的代码可能根本不会返回任何有意义的内容。

这是我的解决方案(Swift 3):

private func stripFileExtension ( _ filename: String ) -> String { var components = filename.components(separatedBy: ".") guard components.count > 1 else { return filename } components.removeLast() return components.joined(separator: ".") } func nameOfApp ( ) -> String { let bundle = Bundle.main if let name = bundle.object(forInfoDictionaryKey: "CFBundleDisplayName") ?? bundle.object(forInfoDictionaryKey: kCFBundleNameKey as String), let stringName = name as? String { return stringName } let bundleURL = bundle.bundleURL let filename = bundleURL.lastPathComponent return stripFileExtension(filename) }

这个解决方案如何更好?

  1. 它将首先检查

    CFBundleDisplayName

    ,如果不存在,则仅回退到 
    CFBundleName

  2. object()

    方法始终在信息字典的本地化版本上运行,因此如果存在本地化,则会自动使用它。

  3. 如果字典中既不存在

    CFBundleDisplayName

    也不存在
    CFBundleName
    ,则代码将回退到仅使用磁盘上的捆绑文件名而不带扩展名(因此“My Cool App.app”将是“My Cool App”),这是一个后备,因此该函数永远不会返回 
    nil


6
投票
let appDisplayName = Bundle.main.infoDictionary?["CFBundleName"] as? String

它是可选的,因此请将其放入 if let 或 Guard 语句中。


4
投票
这个适用于我的

Swift 4.2

guard let dictionary = Bundle.main.infoDictionary else { return "" } if let version: String = dictionary["CFBundleDisplayName"] as? String { return version } else { return "" }
    

3
投票
这在 Xcode 11.0 和 Swift 5 中对我有用

let bundleID = Bundle.main.bundleIdentifier let bundleInfoDict: NSDictionary = Bundle.main.infoDictionary! as NSDictionary let appName = bundleInfoDict["CFBundleName"] as! String print(bundleID!) print(appName)
    

2
投票
这应该更像你正在寻找的:

let infoDictionary: NSDictionary = NSBundle.mainBundle().infoDictionary as NSDictionary! let appName: NSString = infoDictionary.objectForKey("CFBundleName") as NSString NSLog("Name \(appName)")

可能仍然有更好的方法来做到这一点,但它至少在我非常有限的测试中正确返回应用程序名称......


2
投票
试试这个:

extension Bundle { var displayName: String { let name = object(forInfoDictionaryKey: "CFBundleDisplayName") as? String return name ?? object(forInfoDictionaryKey: kCFBundleNameKey as String) as! String } }
    

1
投票
let bundleInfoDict: NSDictionary = NSBundle.mainBundle().infoDictionary! let appName = bundleInfoDict["CFBundleName"] as String
    

1
投票
这个非常适合我

let appName = NSBundle.mainBundle().objectForInfoDictionaryKey("CFBundleDisplayName") as! String
    

1
投票
// Bundle+appName.swift extension Bundle { var appName: String { object(forInfoDictionaryKey: "CFBundleDisplayName") as? String ?? object(forInfoDictionaryKey: "CFBundleName") as? String ?? "" } } // Usage (non optional) let appName = Bundle.main.appName
    

0
投票

适用于 swift 5、iOS 13*

如前所述,它是可选的,因此将其放在保护声明中。我使用结构来做到这一点:

struct Model { struct ProgVariablen{ static var appBundleName:String { get {guard Bundle.main.infoDictionary != nil else {return ""} return Bundle.main.infoDictionary!["CFBundleName"] as! String }//end get }//end computed property static var appBundleShortVersion:String { get {guard Bundle.main.infoDictionary != nil else {return ""} return Bundle.main.infoDictionary ["CFBundleShortVersionString"] as! String }//end get }//end computed property static var appBundleBuild:String { get {guard Bundle.main.infoDictionary != nil else {return ""} return Bundle.main.infoDictionary["CFBundleVersion"] as! String }//end get }//end computed property //initialsieren der Variablen init( appBundleName:String, appBundleShortVersion:String, appBundleBuild:String, ) { // do here nothing for 'let' // do here nothing for 'computed properties' // your other ‘var’ are here like: // ProgVariablen.var1 = var1 }//end init }//end struct ProgVariablen }//end struct Model

用途:

print("Model.ProgVariablen.appBundleName: '\(Model.ProgVariablen.appBundleName)'")
    

0
投票
extension NSApplication { static var name: String { Bundle.main.object(forInfoDictionaryKey: kCFBundleNameKey as String) as? String ?? ProcessInfo.processInfo.processName } }
    

-1
投票
试试这个,

let appName = Bundle.main.infoDictionary?.first(where: {$0.key == "CFBundleDisplayName"})?.value as? String ?? "default name"
    
© www.soinside.com 2019 - 2024. All rights reserved.