也許我誤解你想實現什麼,但是從你的問題和第三個代碼塊聽起來,你想要一個「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