2016-04-12 40 views
1

Karmaşık bir senaryo için basit bir API'ye ulaşmaya çalışıyorum. Verileri eşzamansız olarak alan bir türüm var (aslında bluetooth cihazı). Bu yüzden ile bitirmek çalışıyorum API şudur:Kapatmada jenerik tip döndüren dinamik jenerik parametreler?

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

ben this amazing article bazı iyi fikirler var, bu yüzden bu yukarıda ulaşmak girişiminde aşağıdadır: Ben

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 
    } 
} 

Döndürülen kapatma türü ile ilgili sorun yaşıyorum. Geçilen periferik jenerik tip anahtarına göre güçlü bir şekilde yazılmak istiyorum, ancak bunu nasıl yapacağımı anlayamıyorum veya belki farklı bir yaklaşıma ihtiyacım var mı? Herhangi bir yardım veya yön büyük takdir edilecektir!

cevap

2

service'unuzun değer türünü almak için, oder'de bir genel parametre kullanabilirsiniz. Sipariş kullanmak ise statik olarak yerine kendi alt sınıfının PeripheralKey<T> kullanmanızı öneririm:

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) 
} 

Swift 3.0 olasılıkla böyle tek yapı kullanma izin veren genel türlerdeki statik özellikler koyabilirsiniz salıverilmiş sonra:

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 
    } 
}