gpt4 book ai didi

swift - 如果信号已经发生,如何观察信号并立即接收到 `next` 事件?

转载 作者:可可西里 更新时间:2023-11-01 00:23:21 25 4
gpt4 key购买 nike

我正在尝试包装在网络请求后初始化对象的 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,但这似乎需要一个默认属性,这似乎对此没有意义。

我应该如何处理这件事?

最佳答案

您需要的是多播。然而,ReactiveCocoa 3/4 并没有提供一种简单的方法来做到这一点(与 Rx 相反),因为它们通常会导致大量的复杂性。

有时确实有必要,就像在您的示例中一样,并且可以使用 PropertyType 轻松实现。

我首先创建发出请求的冷信号。那必须是 SignalProducer:

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

如果您按原样公开它,每次此生产者启动时都会产生副作用。要多播这些值,您可以将其包装在属性中并改为公开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 会立即启动。

关于swift - 如果信号已经发生,如何观察信号并立即接收到 `next` 事件?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33946571/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com