1

我有一个通过 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]”

4

1 回答 1

0

嗯,虽然我不太确定问题是什么,但我认为下面的实现可能是你想要的。

extension SignalProducerType where Value == [PrimaryKeyConvertible]
{
    func fetchOnMainThread() -> SignalProducer<[PrimaryKey], Error> {
        return self.map { value in
            value.map { $0.pkValue }
        }
    }
}

尝试这个:

extension SignalProducerType where Value == [PrimaryKeyConvertible]
{
    func fetchOnMainThread<T: PrimaryKeyConvertible>() -> SignalProducer<[T], Error> {
        return self.map { value in
            value.map { $0.pkValue }
        }.map { keys in
            keys.flatMap { T.pkObject($0) }
        }
    }
}
于 2016-03-11T02:48:17.553 回答