2016-04-12 136 views
1

我正試圖爲一個複雜的場景實現一個簡單的API。我有一個類型,它異步檢索數據(實際上是藍牙設備)。所以我想直到結束的API是這樣的:在閉包中返回泛型類型的動態泛型參數?

peripheral.requestData(.Temperature) { value: Double in 
    print(value) 
} 

我得到了一些好的想法來自this amazing article,所以這是我試圖實現以上:

class MyPeripheral { 

    class Keys { 
     static let Temperature = PeripheralKey<Double>("Temperature") 
     static let UserData = PeripheralKey<[String: String]>("UserData") 
    } 

    func requestData(service: Keys, handler: (value: ???Get ValueType from PeripheralKey???) -> Void) { 
     if let service = service as? PeripheralKey<Int> { 
      service.key //Do something 
     } else if let service = service as? PeripheralKey<[String: String]> 
      //Do something else 
     } 
    } 
} 

class PeripheralKey<ValueType>: MyPeripheral.Keys { 
    let key: String 

    init(_ key: String) { 
     self.key = key 
    } 
} 

我在返回的封閉類型中遇到問題。我希望基於傳入的外設泛型類型鍵進行強類型化,但無法掌握如何執行此操作,或者可能需要其他方法?任何幫助或方向將不勝感激!

回答

2

您可以在oder中使用通用參數來獲取您的service的值類型。爲了使用靜態,我建議使用PeripheralKey<T>,而不是它的子類:

class MyPeripheral { 

    class Keys { 
     static let Temperature = PeripheralKey<Double>("Temperature") 
     static let UserData = PeripheralKey<[String: String]>("UserData") 
    } 

    // use a generic parameter T 
    func requestData<T>(service: PeripheralKey<T>, handler: (value: T) -> Void) { 
     // if you do similar things like in your posted link 
     // you can use ("data" has to be defined by you): 
     // data[service.key] as! T 
    } 
} 

// make class final as long as you don't subclass it 
final class PeripheralKey<ValueType>: MyPeripheral.Keys { 
    let key: String 

    init(_ key: String) { 
     self.key = key 
    } 
} 

let peripheral = MyPeripheral() 
// here you can omit the explicit Double declaration 
peripheral.requestData(.Temperature) { value in 
    print(value) 
} 

後雨燕3.0得到了釋放,你可能可以把靜態屬性在泛型類型,它允許你只使用一個結構是這樣的:

struct PeripheralKey<ValueType> { 

    static let Temperature = PeripheralKey<Double>("Temperature") 
    static let UserData = PeripheralKey<[String: String]>("UserData") 

    let key: String 

    init(_ key: String) { 
     self.key = key 
    } 
}