如何在 Swift 中使用键值编码获取全局常量?

How do you fetch a global constant using key-value coding in Swift?

我正在编写一个方法,它将给出 CNPostalAddress 元素的本地化名称。我试图检索的本地化密钥是全局常量。

/// Get the localised name of a CNPostalAddress element
///
/// - Parameter field: CNPostalAddress element name (Street, SubLocality, City, SubAdministrativeArea, State, PostalCode, Country, ISOCountryCode)
/// - Returns: localized name of the address field


func localizedAddressFieldName(for field: String) -> String? {
    let keyPathKey = "CNPostalAddress\(field)Key"

    if let localizationKey = value(forKey: keyPathKey) as? String {
        return CNPostalAddress.localizedString(forKey: localizationKey)
    } else {
        return nil
    }
}

但是,应用程序在获取具有以下日志的 localizationKey 时崩溃:

Terminating app due to uncaught exception 'NSUnknownKeyException', reason: '[<MyProject.MyViewController 0x7fd83d81c8b0> valueForUndefinedKey:]: this class is not key value coding-compliant for the key CNPostalAddressStreetKey.'

CNPostalAddressStreetKey 是一个有效的密钥,如 Apple docs 所示,但它是一个全局常量。

解决方案

extension CNPostalAddress {
    class func localizedAddressFieldName(for field: String) -> String? {
        let localizationKey = field.decapitalizingFirstLetter()
        return CNPostalAddress.localizedString(forKey: localizationKey)
    }
}

extension String {
    func decapitalizingFirstLetter() -> String {
        let firstLetterLowercase = String(prefix(1)).lowercased()
        return firstLetterLowercase + String(dropFirst())
    }
}

这是因为您可能不得不改用这些变量:

print("\(CNPostalAddress.localizedString(forKey: "subLocality"))")
print("\(CNPostalAddress.localizedString(forKey: "street"))")

所以而不是

let keyPathKey = "CNPostalAddress\(field)Key"

你应该使用

let keyPathKey = "\(field)"

它区分大小写,因此您可能需要进行一些调整。

参见 here

首先 value(forKey: keyPathKey)NSKeyValueCoding 协议中定义的方法,您在 viewController 中调用该方法,这就是为什么要崩溃以避免崩溃的原因,您必须实现该方法在你的 ViewController

override func value(forKey key: String) -> Any? {

}

但无论如何我认为您不需要在第一个实例中调用此方法

func localizedAddressFieldName(for field: String) -> String? {
    let localizationKey = "CNPostalAddress\(field)Key"

    return CNPostalAddress.localizedString(forKey: localizationKey)
}

如果您的密钥未在 CNPostalAddress 中定义,则结果将为空字符串