我可以使用泛型将 NSNumber 转换为 swift 中的 T 吗?

Can I use generics to cast NSNumber to T in swift?

我想要的

func safeGet<T>() -> T {
    let value = magic()
    if let typedValue = value as? T {
        return typedValue
    }
}

这不起作用的原因是您不能在 swift

中执行 <NSNumber> as Int

我在 <what do I put here?> 占位符中放了什么?

func safeGet<T>() -> T {
    let value = magic()
    if let typedValue = value as? NSNumber {
        return <what do I put here?>
    } else if let typedValue = value as? T {
        return typedValue
    }
}

最后我这样做是为了能够以抛出错误的方式从字典中获取类型化的值。是这样用的

let name:String = dictionary.safeGet("name")

let name = dictionary.safeGet("name") as String`

源代码:


import Foundation

extension Dictionary {
    func safeGet<T>(key:Key) throws -> T {
        if let value = self[key] as? AnyObject {
            if let typedValue = value as? T {
                return typedValue
            }

            let typedValue: T? = parseNumber(value)
            if typedValue != nil {
                return typedValue!
            }

            let typeData = Mirror(reflecting: value)
            throw generateNSError(
                domain: "DictionaryError.WrongType",
                message: "Could not convert `\(key)` to `\(T.self)`, it was `\(typeData.subjectType)` and had the value `\(value)`"
            )
        } else {
            throw generateNSError(
                domain: "DictionaryError.MissingValue",
                message: "`\(key)` was not in dictionary. The dictionary was:\n\(self.description)"
            )
        }
    }

    private func parseNumber<T>(value: AnyObject) -> T? {
        if Int8.self == T.self {
            if let numericValue = value as? NSNumber {
                return numericValue.charValue as? T
            } else if let stringValue = value as? String {
                return Int8(stringValue) as? T
            }
        } else if Int16.self == T.self {
            if let numericValue = value as? NSNumber {
                return numericValue.shortValue as? T
            } else if let stringValue = value as? String {
                return Int16(stringValue) as? T
            }
        } else if Int32.self == T.self {
            if let numericValue = value as? NSNumber {
                return numericValue.longValue as? T
            } else if let stringValue = value as? String {
                return Int32(stringValue) as? T
            }
        } else if Int64.self == T.self {
            if let numericValue = value as? NSNumber {
                return numericValue.longLongValue as? T
            } else if let stringValue = value as? String {
                return Int64(stringValue) as? T
            }
        } else if UInt8.self == T.self {
            if let numericValue = value as? NSNumber {
                return numericValue.unsignedCharValue as? T
            } else if let stringValue = value as? String {
                return UInt8(stringValue) as? T
            }
        } else if UInt16.self == T.self {
            if let numericValue = value as? NSNumber {
                return numericValue.unsignedShortValue as? T
            } else if let stringValue = value as? String {
                return UInt16(stringValue) as? T
            }
        } else if UInt32.self == T.self {
            if let numericValue = value as? NSNumber {
                return numericValue.unsignedIntValue as? T
            } else if let stringValue = value as? String {
                return UInt32(stringValue) as? T
            }
        } else if UInt64.self == T.self {
            if let numericValue = value as? NSNumber {
                return numericValue.unsignedLongLongValue as? T

            } else if let stringValue = value as? String {
                return UInt64(stringValue) as? T
            }
        } else if Double.self == T.self {
            if let numericValue = value as? NSNumber {
                return numericValue.doubleValue as? T
            } else if let stringValue = value as? String {
                return Double(stringValue) as? T
            }
        } else if Float.self == T.self {
            if let numericValue = value as? NSNumber {
                return numericValue.floatValue as? T
            } else if let stringValue = value as? String {
                return Float(stringValue) as? T
            }
        } else if String.self == T.self {
            if let numericValue = value as? NSNumber {
                return numericValue.stringValue as? T
            } else if let stringValue = value as? String {
                return stringValue as? T
            }
        }
        return nil
    }

    private func generateNSError(domain domain: String, message: String) -> NSError {
        return NSError(
            domain: domain,
            code: -1,
            userInfo: [
                NSLocalizedDescriptionKey: message
            ])
    }
}