RxSwift запускает наблюдаемое выполнение

У меня есть наблюдаемая Subject, представляющая результат сетевого запроса, который необходимо доставить нескольким подписчикам.

Я могу использовать метод ReplaySubject из буфера 1 и publish(). Однако сетевой запрос выполняется только один раз.

Я хотел бы вызвать событие выборки в любой момент в будущем. Как я могу вызвать новый запрос?

В настоящее время у меня есть объект Service, который содержит ReplaySubject и имеет метод reload(), который запускает сетевой запрос и публикует результат в aReplaySubject.

Есть ли какой-либо метод для Observable, который может "обновить" его и доставить новое значение всем текущим подписчикам?


person Richard Topchii    schedule 26.04.2018    source источник


Ответы (1)


Если я правильно интерпретирую этот вопрос, это довольно распространенная проблема в RxSwift. Вы должны иметь возможность воссоздавать свой сетевой запрос Observable каждый раз, когда ваша выборка "запускается", но вам нужно, чтобы эти результаты доставлялись на один Observable, который создается только один раз и имеет несколько подписчиков. Это делается с помощью flatMap:

struct Service {
    var resultsObservable: Observable<Results> {
        return resultsSubject.asObservable()
    }

    private let resultsSubject: ReplaySubject<Results> = .create(bufferSize: 1)
    private let reloadSubject = PublishSubject<Void>()
    private let disposeBag = DisposeBag()

    init() {
        bindFetch()
    }

    func reload() {
        reloadSubject.onNext(())
    }

    private func bindFetch() {
        reloadSubject
            .asObservable()
            .flatMap(fetch)
            .bind(to: resultsSubject)
            .disposed(by: disposeBag)
    }

    private func fetch() -> Observable<Results> {
        // URLSession just one example
        let urlRequest = URLRequest(url: URL(string: "https://apple.com")!)
        return URLSession
            .shared
            .rx
            .data(request: urlRequest)
            .map(Results.init)
            .catchErrorJustReturn(Results.empty())
    }
}

В этом примере вы можете подписаться на resultsObservable несколько раз, и каждое из них должно обновляться после появления нового reload().

person daltonclaybrook    schedule 01.05.2018
comment
Спасибо за ваш ответ. Я реализовал желаемую функциональность так, как вы описали в своем ответе. Однако вопрос заключается в том, можно ли обновить resultsObservable, вызвав некоторый вызов метода для самого наблюдаемого, а не метод reload() для службы. - person Richard Topchii; 02.05.2018
comment
В этом примере вместо вызова reload() вы можете привязать Observable к reloadSubject, например, UIButton.rx.tap - person daltonclaybrook; 03.05.2018