我正在尝试使用以下签名在Dictionary
上编写扩展方法:
func firstNonNilObjectForKey(keys: [Key], ofClass aClass: Any.Type = String.self) -> Value?
这是为了帮助我处理JSON词典,我经常需要第一个非null值,但有时JSON包含null
本身作为值,在Cocoa中转换为NSNull
用法如下:
let dict: [String:AnyObject] = [...]
let myValue = dict.firstNonNilObjectForKey([ "key1", "key2" ]) as? String
问题是实现性的 - 如何匹配班级:
if let value = self[key] {
if value is aClass { ... } <--- error: aClass is not a type
if let castedValue = value as? aClass { ... } <--- error: ditto
let type = value.dynamicType
if type == aClass { ... } <--- no error, but doesn't handle subclasses!
// Cannot use value.isKindOfClass() since value may be Any
}
我想到了另一种选择:
func firstNonNilObjectForKey<ReturnValueType>(keys: [Key]) -> ReturnValueType?
允许实现为
if let value = self[key] as? ReturnValueType { ... }
但:
- 这里我不能设置默认类型(我主要需要String.Type
)。
- 我真的不确定如何调用它:
let value = dict.firstNonNilObjectForKey([ "key1", "key2" ]) as? String <--- error: Cannot invoke 'firstNonNilObjectForKey' with an argument list of type '([String])'
let value = dict.firstNonNilObjectForKey<String>([ ... ]) <--- error: Cannot explicitly specialize a generic function
我希望这不是重复,但这里大多数类似的问题只是处理你与已知类匹配的情况。
答案 0 :(得分:3)
我不确定我是否完全符合要求,但是这样的东西可以为你工作吗?
extension Dictionary {
func firstNonNilObjectForKey(keys: [Key]) -> String? {
return self.firstNonNilObjectForKey(keys, ofClass: String.self)
}
func firstNonNilObjectForKey<T>(keys: [Key], ofClass aClass: T.Type) -> T? {
for k in keys {
if let v = self[k] as? T {
return v
}
}
return nil
}
}
let dict = ["key1": 2, "key2": "Foo"]
let aString = dict.firstNonNilObjectForKey(["key1", "key2"]) // "Foo"
let anInt = dict.firstNonNilObjectForKey(["key1", "key2"], ofClass: Int.self) // 2
这里的主要问题是我使用重载而不是默认参数,这似乎与swift类型检查器相处得不好。