2016-02-13 197 views
0

我使用“JSON到我自己的班级”,我真的很头疼,类型转换。典型的转换是这样的:如何传递类型(例如String)作为函数参数?

I need: "55" (JSON) -> 55 (Int) 
My path: AnyObject? -> String -> Int 

斯威夫特的转化率不AnyObject( “55”)为INT( “55”)直接,斯威夫特认为, “55” 始终是字符串。所以我写的辅助方法:

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 
} 

回答

1

也许我误解你想实现什么,但是从你的问题和第三个代码块听起来,你想要一个“jsonDirectToAnything”通用函数;尝试将JSON from参数转换为使用JSON (AnyObject) -> String -> SomeType管道通过type参数传递的类型。在上面的代码示例中(最后一个代码块),即使在显示您想要一些通用的<T>(string)转换(它被分配给返回类型)时,返回类型也被设置为Int,所以我将假定使用返回类型Int不是您“重新使用后,而是使用泛型返回类型(如果不是这样的话,那么这个问题对我来说并没有多大意义)。


无论如何,对于技术讨论:您可以创建约束到符合协议类型的通用返回类型这样的功能---说StringInitializable ---包括一个蓝图(failable)初始值设定项由String个实例组成。将希望能够使用“generic”jsonDirect方法的类型扩展为StringInitializable,并且如果需要,可以实现协议所设计的String初始化程序。在下面的例子中,我已经在StringInitializable中蓝图初始化程序init?(_ text: String)。这个可分解的初始化器很容易用于例如DoubleString类型,但是需要为(例如)封装实现(就像包装一样)。将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转化成IntDoubleString以及一个自定义类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 
相关问题