return 闭包中泛型类型的动态泛型参数?

Dynamic generic parameters that return generic type in closure?

我正在努力为复杂的场景实现一个简单的 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
    }
}

我在处理返回的闭包类型时遇到了问题。我想根据传入的外围通用类型键进行强类型化,但无法掌握如何做到这一点,或者可能需要不同的方法?任何帮助或指导将不胜感激!!

您可以在 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
    }
}