Предупреждение об устаревании ничего мне не говорит - вместо этого используйте свойства. 'буфер' будет удален в RAC 5.0
Какие свойства? Может ли кто-нибудь привести четкий пример. Спасибо.
buffer(0)
Signal.pipe
, но менее эффективно.buffer(1)
MutableProperty
без гарантии постоянного наличия текущего значения во время компиляции. Вот почему мы рекомендуем свойства выше buffer(1)
в сообщении об отказе от поддержки.buffer(n)
для n> 1SignalProducer.replayLazily
как замену, хотя семантика будет немного другой.@andersio о, спасибо большое, я не думал о _right_ свойствах
Hy,
Что, если я захочу отправить сообщение об ошибке в буферизованный SignalProducer?
В MutableProperty нет ошибки в Signal или SignalProducer
С Уважением
Если вам действительно нужна старая семантика buffer
, вы можете создать канал Signal
, обернуть его SignalProducer
и использовать replayLazily
.
Обратите внимание, что replayLazily
начинает кэширование событий, только если оно когда-либо было запущено.
let (signal, observer) = Signal<Int, TestError>.pipe()
let replayedProducer = SignalProducer(signal: signal).replayLazily(1)
// Start the buffering immediately.
replayedProducer.start()
Спасибо, это то, что я искал
Спасибо,
replayLazily, кажется, имеет побочный эффект.
взгляните на пример ниже
let (signal, observer) = Signal<Int, NSError>.pipe()
let replayedProducer = SignalProducer(signal: signal).replayLazily(1)
// Start the buffering immediately.
replayedProducer.start()
func someAsyncProcedure() {
observer.send(error: NSError()) //<------------ LINE 2
}
func someProcedure {
replayedProducer.startWithResult {
switch($0) {
case .success(let value):
print(value)
case .failure(let error):
print(error) //<------------ LINE 1
}
}
someAsyncProcedure()
}
someProcedure() //everything is fine
someProcedure() //LINE 1 is called before LINE 2
Я не читал код replayLazily, но, похоже, использовал кешированное значение вместо использования значения, отправленного наблюдателем. Проблема в том, что когда наблюдатель отправляет значение, вместо успеха вызывается процедура отказа.
Чтобы решить эту проблему, мне нужно создавать сигнал каждый раз, когда я вызываю someProcedure, не думаю, что это хорошая практика ... любой комментарий приветствуется
Когда вы во второй раз вызываете someProcedure
, основной производитель уже завершил работу с ошибкой, которую вы отправили при первом вызове someProcedure
(с someAsyncProcedure
).
Воспроизведенный продюсер кэшировал эту ошибку для вас, и поэтому вы получаете «Строку 1» перед «Строкой 2» - она воспроизвела ошибку.
Обратите внимание, что отправка ошибки означает завершение потока событий.
@andersio Спасибо за ответ.
Я предполагаю, что, поскольку производитель завершен, можно создать новый сигнал для обработки такой асинхронной процедуры
class SomeClass {
private var observer: Observer<String, NSError>!
//delegate method async called from other thread
func someAsyncProcedure() {
observer.send(error: NSError()) //<------------ LINE 2
}
func someProcedure -> SignalProducer<String, NSError> {
let producer SignalProducer<String, NSError> { [weak self] sink, _ in
self!.observer = sink
}
return producer
}
}
func xxx() {
SomeClass.someProcedure().startWithResult {
switch($0) {
case .success(let value):
print(value)
case .failure(let error):
print(error) //<------------ LINE 1
}
}
}
xxx()
xxx()
Думаю, я хочу здесь семантику будущего ...
Я прочитал # 2744 и заметил
PropertyType имеет ту же семантику, что и SignalProducer.buffer.
Но, как сказал Бенджи-бо, Property не выдает ошибок. Кажется, мне нужно использовать два свойства для обработки ошибок, одно - это свойство успеха, обертывающее нужное мне значение, другое - свойство ошибки, и я должен наблюдать за ними обоими, верно?
Кажется, что вы хотите обернуть шаблон делегата как потоки значений, в то время как делегат запускается в результате запуска производителя.
В этом случае, я думаю, вам будет лучше с внутренним сигналом Signal<Result<Value, Error>, NoError>
и передать ему результаты обратного вызова делегата. Тогда вы можете выводить из него производителей.
let asyncResult: Signal<Result<Value, Error>, NoError>
func work() -> SignalProducer<Value, Error> { observer, disposable in
// Mutual exclusion via semaphore or queues, if necessary.
disposable += asyncResult.observeValues { result in
switch result {
case let .success(value):
observer.send(value: value)
observer.sendCompleted()
case let .failure(error):
observer.send(error: error)
}
}
startTheAsyncWorkThatCallbacksViaDelegate()
}
@andersio Спасибо за терпение, проблема решена 👍
Самый полезный комментарий
Если вам действительно нужна старая семантика
buffer
, вы можете создать каналSignal
, обернуть егоSignalProducer
и использоватьreplayLazily
.Обратите внимание, что
replayLazily
начинает кэширование событий, только если оно когда-либо было запущено.