2

ネットワーク リクエストの後にオブジェクトを初期化する API 呼び出しをラップしようとしています。新しいオブザーバーごとにネットワーク要求が発生することを望まないので、私が理解しているように、SignalProducer. ただし、単一Signalの を使用すると、最初の使用のみがnextイベントを受け取り、新しいサブスクライバーは現在の値を受け取ることはありません。これをどのように行う必要がありますか?私はおそらく、RAC で根本的に間違ったことをしているのでしょう。

extension SparkDevice {
    static func createMainDeviceSignal() -> Signal<SparkDevice, NSError> {
        return Signal {
            sink in
            SparkCloud.sharedInstance().getDevices { (sparkDevices: [AnyObject]!, error: NSError!) -> Void in
                if let error = error {
                    sink.sendFailed(error)
                }
                else {
                    if let devices = sparkDevices as? [SparkDevice] {
                        if devices.count > 0 {
                            sink.sendNext(devices[0])
                        }
                    }
                }
            }
            return nil
        }
    }
}

class DeviceAccess {
    let deviceSignal: Signal<SparkDevice, NSError>

    init() {
        self.deviceSignal = SparkDevice.createMainDeviceSignal()
    }
 }

の使用を検討しMutablePropertyましたが、これには意味がないように見えるデフォルト プロパティが必要なようです。

これについて実際にどうすればよいですか?

4

1 に答える 1

6

必要なのはマルチキャストです。ただし、ReactiveCocoa3/4 は (Rx とは対照的に) それを行う簡単な方法を提供しません。

あなたの例のように、それが本当に必要な場合があり、を使用して簡単に実装できますPropertyType

まず、リクエストを行うコールド シグナルを作成します。それはでなければなりませんSignalProducer

private func createMainDeviceSignalProducer() -> SignalProducer<SparkDevice, NSError> {
    return SignalProducer { observer, _ in
        ....
    }
}

startこれをそのまま公開すると、このプロデューサーがedされるたびに副作用が発生します。これらのmulticast値に対して、プロパティでラップし、代わりにを公開できます。propertyproducer

public final class DeviceAccess {
    public let deviceProducer: SignalProducer<SparkDevice, NoError>
    private let deviceProperty: AnyProperty<SparkDevice?>

    init() {
        self.deviceProperty = AnyProperty(
           initialValue: nil, // we can use `nil` to mean "value isn't ready yet"         
           producer: SparkDevice.createMainDeviceSignal()
                        .map(Optional.init) // we need to wrap values into `Optional` because that's the type of the property
                        .flatMapError { error in 
                              fatalError("Error... \(error)") // you'd probably want better error handling

                              return .empty // ignoring errors, but you probably want something better.
                        }
        )

        self.deviceProducer = deviceProperty
              .producer    // get the property producer
              .ignoreNil() // ignore the initial value
    }
 }

DeviceAccess.deviceProducer副作用を繰り返す代わりに、基になるプロデューサーによって発行された値を再生するようになりました。ただし、遅延ではないことに注意してください。基SignalProducerになるものはすぐに開始されます。

于 2015-12-01T00:12:16.353 に答える