2016-02-13 89 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 
相關問題