我有一个通过 PrimaryKey 获取数据库对象的协议
typealias PrimaryKey = String
protocol PrimaryKeyConvertible {
var pkValue : PrimaryKey { get }
static func pkObject(key: PrimaryKey) -> Self?
}
并且我想扩展 SignalProducerType 以便能够对该类型的 SignalProducer.Value 进行操作。
因此,单个对象扩展(不是数组中的单个)可以正常工作并实现如下:
extension SignalProducerType
where Value: PrimaryKeyConvertible
{
func fetchOnMainThread() -> SignalProducer<Value?, Error> {
return
self.map{ (obj: Value) -> PrimaryKey in
return obj.pkValue
}
.observeOn(UIScheduler())
.map{ (key: PrimaryKey) -> Value? in
return Value.pkObject(key)
}
}
}
但是当我尝试在这些元素的数组上实现它时,我遇到了一些编译挑战:
extension SignalProducerType
{
func fetchOnMainThread<P: PrimaryKeyConvertible where Self.Value == Array<P>>() -> SignalProducer<[P], Error> { //(1)
return self.map({ (value: Self.Value) -> [PrimaryKey] in
return value.map{ $0.pkValue } //(2)
})
}
}
(1) 我怀疑签名没有正确地将想法传达给编译器
(2) 产生以下错误:
在没有更多上下文的情况下,表达式的类型是模棱两可的
我要解决的问题是如何让编译器识别 SignalProducer 正在运行的Array<P>
P 是 PrimaryKeyConvertible 并相应地对其.map
进行操作...
我目前对数组问题的解决方案是使用下面列出的通用函数来实现:
func fetchOnMainThread<Value: PrimaryKeyConvertible, Error: ErrorType>
(signal: SignalProducer<[Value], Error>) -> SignalProducer<[Value], Error> {
return signal
.map{ (convertibles: [Value]) -> [PrimaryKey] in
return convertibles.map { $0.pkValue }
}
.observeOn(UIScheduler())
.map{ (keys: [PrimaryKey]) -> [Value] in
return keys.flatMap{ Value.pkObject($0) }
}
}
然后用于例如:
extension GoogleContact: PrimaryKeyConvertible {...}
extension GoogleContact {
static func fetchGoogleContactsSignal() -> SignalProducer<[GoogleContact], GoogleContactError> { ...}
}
呼叫站点将是:
let signal = fetchOnMainThread(GoogleContacts.fetchGoogleContactsSignal()).onNext...
我更愿意将它作为一个扩展,它会像往常一样流动
GoogleContacts
.fetchGoogleContactsSignal()
.fetchOnMainThread()
更新
我尝试过的另一个版本的功能:(@J.Wang)
extension SignalProducerType
where Value == [PrimaryKeyConvertible]
{
func fetchArrayOnMainThread2<T: PrimaryKeyConvertible>() -> SignalProducer<[T], Error> {
return self
.map{ (values: Self.Value) -> [PrimaryKey] in
return values.map{ $0.pkValue }
}
.deliverOnMainThread()
.map{ (keys: [PrimaryKey]) -> [T] in
return keys.flatMap{ T.pkObject($0) }
}
}
}
let signal =
GoogleContacts
.fetchGoogleContactsSignal()
.fetchArrayOnMainThread2() //(3)
(3) 产生错误:
“[PrimaryKeyConvertible]”不能转换为“[GoogleContact]”