【问题标题】:Handling exception thrown by Foundation object?处理Foundation对象抛出的异常?
【发布时间】:2014-09-14 17:54:08
【问题描述】:

我有一个 swift 函数可以从主包的 localizedInfoDictionary 获取本地化的应用程序名称,并带有一些后备情况。

private func defaultAppName() -> String {
    var name: NSString = ""
    // Check for a localized version of the CFBundleDisplayName
    var mainBundle = NSBundle.mainBundle()
    // EXC_BAD_ACCESS HERE, despite the optional
    var mainBundleInfoDictionary: Dictionary<NSObject, AnyObject>? = mainBundle.localizedInfoDictionary

    if let infoDictionary = mainBundleInfoDictionary {
        name = infoDictionary["CFBundleDisplayName"] as NSString

        if (name.length == 0) {
            name = infoDictionary[kCFBundleNameKey] as NSString
        }
    }

    if (name.length == 0) {
        mainBundleInfoDictionary = mainBundle.infoDictionary

        if let infoDictionary = mainBundleInfoDictionary {
            name = infoDictionary["CFBundleDisplayName"] as NSString

            if (name.length == 0) {
                name = infoDictionary[kCFBundleNameKey] as NSString
            }
        }
    }

    return name
}

我知道这并不简洁,但我仍在学习 swift。我看到的问题是访问mainBundle.localizedInfoDictionary 在找不到时不会返回零,而是抛出EXC_BAD_ACCESS。我不能保证在使用此功能的应用程序中会有本地化信息,但标准的快速处理选项的方法在这里不起作用。

如何捕获 NSBundle 的 localizedInfoDictionary 调用引发的异常或调整我的 swift 代码以继续前进?

【问题讨论】:

标签: ios swift ios8 optional-parameters foundation


【解决方案1】:

首先,这是 Swift 中的一个错误,应该向 bugreport.apple.com 报告。此方法用于返回隐式可选。他们应该将其转换为显式可选,而是将其转换为非可选,因为该方法可以返回nil

NSDictionary *mainBundleInfoDictionary = [[NSBundle mainBundle] localizedInfoDictionary];
NSLog(@"%@", mainBundleInfoDictionary);

但您通常不需要localizedInfoDictionary。你可以直接问NSBundle

private func defaultAppName() -> String {
  let mainBundle = NSBundle.mainBundle()
  let displayName = mainBundle.objectForInfoDictionaryKey("CFBundleDisplayName") as? String
  let name = mainBundle.objectForInfoDictionaryKey(kCFBundleNameKey) as? String
  return displayName ?? name ?? "Unknown"
}

【讨论】:

  • 谢谢! rdar://18332365
  • 在现代 Swift 中,let name = 不会产生模棱两可的类型错误
【解决方案2】:

也许直接访问对象会很幸运?至少我让 Playground 在这样做时表现得更好(没有崩溃):

let name = mainBundle.objectForInfoDictionaryKey("CFBundleDisplayName") as? String

我知道这并不能直接解决本地化问题。为了提供可行的建议,您可以在Localizable.strings 中创建自己的(重复)密钥。

【讨论】:

  • 这将成为一些开源软件的一部分。我不能保证实施者会本地化他/她的应用程序
猜你喜欢
  • 1970-01-01
  • 2013-07-24
  • 2011-06-25
  • 2011-10-10
  • 2011-11-23
  • 1970-01-01
  • 1970-01-01
  • 2013-06-08
  • 2011-02-21
相关资源
最近更新 更多