在闭包中返回泛型类型的动态泛型参数?

时间:2016-04-12 14:25:53

标签: swift generics swift2 swift2.2

我正在尝试为复杂的方案实现一个简单的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
    }
}

我遇到了返回的闭包类型问题。我想基于传入的外围通用类型键进行强类型化,但是不能掌握如何做到这一点,或者可能需要一种不同的方法?任何帮助或方向将不胜感激!!

1 个答案:

答案 0 :(得分: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)
}

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