也许我误解你想实现什么,但是从你的问题和第三个代码块听起来,你想要一个“jsonDirectToAnything
”通用函数;尝试将JSON from
参数转换为使用JSON (AnyObject) -> String -> SomeType
管道通过type
参数传递的类型。在上面的代码示例中(最后一个代码块),即使在显示您想要一些通用的<T>(string)
转换(它被分配给返回类型)时,返回类型也被设置为Int
,所以我将假定使用返回类型Int
不是您“重新使用后,而是使用泛型返回类型(如果不是这样的话,那么这个问题对我来说并没有多大意义)。
无论如何,对于技术讨论:您可以创建约束到符合协议类型的通用返回类型这样的功能---说StringInitializable
---包括一个蓝图(failable)初始值设定项由String
个实例组成。将希望能够使用“generic”jsonDirect
方法的类型扩展为StringInitializable
,并且如果需要,可以实现协议所设计的String
初始化程序。在下面的例子中,我已经在StringInitializable
中蓝图初始化程序init?(_ text: String)
。这个可分解的初始化器很容易用于例如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