#ios #swift #combine #combinelatest
Вопрос:
Я наблюдаю неожиданное поведение в отношении combineLatest, если у внутренних издателей есть subscribe(on:)
, поток combineLatest не выдает никакого значения.
Примечания:
- С оператором Zip работает
- Перемещение подписки(вкл.:) / получения(вкл.:) в поток combineLatest также работает. Но в данном конкретном случае внутренние издатели определяют свою подписку/получение, потому что они (повторно)используются в других местах.
- Добавление подписки(вкл.:)/получения(вкл.:) только для одного из внутренних издателей также работает, поэтому проблема как раз в том, когда они есть у обоих.
func makePublisher() -> AnyPublisher<Int, Never> {
Deferred {
Future { promise in
DispatchQueue.global(qos: .background).asyncAfter(deadline: .now() 3) {
promise(.success(Int.random(in: 0...3)))
}
}
}
.subscribe(on: DispatchQueue.global())
.receive(on: DispatchQueue.main)
.eraseToAnyPublisher()
}
var cancellables = Set<AnyCancellable>()
Publishers.CombineLatest(
makePublisher(),
makePublisher()
)
.sink { completion in
print(completion)
} receiveValue: { (a, b) in
print(a, b)
}.store(in: amp;cancellables)
Это ошибка объединения или ожидаемое поведение? У вас есть какие-либо идеи о том, как можно настроить такой поток, в котором внутренние пользователи могут определить свой собственный планировщик подписки?
Комментарии:
1. Какой у тебя вопрос?
2. @NewDev только что обновил вопрос
Ответ №1:
Да, это ошибка. Мы можем упростить тестовый случай до этого:
import Combine
import Dispatch
let pub = Just("x")
.subscribe(on: DispatchQueue.main)
let ticket = pub.combineLatest(pub)
.sink(
receiveCompletion: { print($0) },
receiveValue: { print($0) })
Это никогда ничего не печатает. Но если вы прокомментируете subscribe(on:)
оператора, он напечатает то, что ожидается. Если вы оставите subscribe(on:)
, но вставите несколько print()
операторов, вы увидите, что CombineLatest
оператор никогда не отправляет запрос вверх по потоку.
Я предлагаю вам скопировать переопределение CombineX CombineLatest
и утилиты , которые ему необходимо скомпилировать (реализации Lock
CombineX и LockedAtomic
, я думаю). Я тоже не знаю, работает ли версия CombineX, но если она глючит, по крайней мере, у вас есть исходный код и вы можете попытаться его исправить.