我正在使用“JSON到我自己的班级”,我对类型转换感到非常头痛。典型的转换如下:
I need: "55" (JSON) -> 55 (Int)
My path: AnyObject? -> String -> Int
Swift没有直接将AnyObject(“55”)转换为Int(“55”),Swift认为“55”总是String。所以我写了辅助方法:
internal func jsonDirectToInt(from: AnyObject?) -> Int? {
guard let string = from as? String,
let int = Int(string) else { return nil }
return int
}
我的问题:我可以将类型传递给函数作为参数,所以我可以这样写:
internal func jsonDirectToInt(from: AnyObject?, type: <T>) -> Int? {
guard let string = from as? String,
let int = <T>(string) else { return nil }
return int
}
答案 0 :(得分:1)
可能我误解了你想要实现的目标,但是从你的问题和随后的第三个代码块听起来你想要一个“jsonDirectToAnything
”泛型函数;尝试使用from
管道将JSON type
参数转换为通过JSON (AnyObject) -> String -> SomeType
参数传递的类型。在上面的代码示例(最后一个代码块)中,即使显示您希望进行一些通用Int
转换(指定为返回类型),您的返回类型也会设置为<T>(string)
,因此我将假设使用返回类型Int
不是你想要的,而是使用泛型返回类型(如果没有;这个问题对我来说真的没有意义)。
无论如何,对于技术讨论:你可以创建这样一个函数,其泛型返回类型被约束为符合协议的类型---比如StringInitializable
---包括一个(可用的)蓝图String
个实例的初始化程序。您可以将希望能够使用“通用”jsonDirect
方法的类型扩展到StringInitializable
,如果需要,还可以实现协议蓝图的String
初始化程序。在下面的示例中,我在init?(_ text: String)
中使用了蓝图初始值设定项StringInitializable
。这种可用的初始化器很容易本地可用于例如Double
和String
类型,但需要实现(仅作为包装),例如将Int
扩展到协议。
最后请注意,在我们继续之前,存在几个用于处理JSON数据到本机Swift类型转换的现有工具,例如
针对您的具体问题的示例解决方案:
/* Protocol with blueprint for failable initializer by String */
protocol StringInitializable {
init?(_ text: String)
}
/* Extend type types you want to use "generically" in 'jsonDirect' method */
extension Double : StringInitializable { } // already has a 'init?(_ text: String)', OK
extension String : StringInitializable { } // already has a 'init?(_ text: String)', OK
extension Int : StringInitializable { // point to 'init(_:radix:)' initializer
init?(_ text: String) {
guard let foo = Int.init(text, radix: 10) else {
return nil
}
self = foo
}
}
/* Your own class */
class MyClass: StringInitializable {
let foo : Int?
required init?(_ text: String) {
foo = Int(text)
}
}
/* jsonDirect for (attempted) type conversion from AnyObject to
generic type, where the latter is constrained to types conforming
to protocol 'StringInitializable' */
func jsonDirect<T: StringInitializable>(from: AnyObject?, toType _ : T.Type) -> T? {
guard let foo = from as? String, let bar = T(foo) else {
return nil
}
return bar
}
将JSON转换为Int
,Double
和String
以及自定义类MyClass
的示例用法:
/* Example usage */
var myJSONInt : AnyObject = "55"
var myJSONInvalidInt : AnyObject = "foo"
var myJSONDouble : AnyObject = "55.3"
var myJSONString : AnyObject = "Foo"
/* Attempt json -> specified type conversions */
let fooInt = jsonDirect(myJSONInt, toType: Int.self)
let fooMyClass = jsonDirect(myJSONInt, toType: MyClass.self)
let fooInvalidInt = jsonDirect(myJSONInvalidInt, toType: Int.self)
let fooDouble = jsonDirect(myJSONDouble, toType: Double.self)
let fooIntString = jsonDirect(myJSONInt, toType: String.self)
/* Results */
print(fooInt.dynamicType, ": value =", fooInt ?? "nil")
// Optional<Int> : value = 55
print(fooMyClass.dynamicType, ": value =", fooMyClass?.foo ?? "nil")
// Optional<MyClass> : value = 55
print(fooInvalidInt.dynamicType, ": value =", fooInvalidInt ?? "nil")
// Optional<Int> : value = nil
print(fooDouble.dynamicType, ": value =", fooDouble ?? "nil")
// Optional<Double> : value = 55.3
print(fooIntString.dynamicType, ": value =", fooIntString ?? "nil")
// Optional<String> : value = 55