Как использовать BehaviorRelay в качестве альтернативы переменной в RxSwift?
по состоянию на RxSwift4,Variable
переехал в Deprecated.swift
маркировка возможного осуждения Variable
в будущем. Альтернативный предложил Variable
is BehaviorRelay
. При публикации этого вопроса, так как я не смог найти большую часть учебника в интернете с помощью BehaviorRelay
размещаю такой фундаментальный вопрос здесь в SO.
предположим, что у меня есть вызов webService, и я получаю кусок данных, который является JSONArray, при разборе объекта JSON один за другим Я обновляю значение своей переменной собственность
вот мое объявление переменной
var myFilter = Variable<[MyFilterModel]>([MyFilterModel(data: "{:}")])
при получении нового элемента каждый раз, когда я буду обновлять свою переменную как
myFilter.value.append(newModel)
поскольку переменная была привязана к CollectionView, collectionVie немедленно обновит свой пользовательский интерфейс новым добавленным объектом.
проблема с BehaviorRelay
теперь моя декларация выглядит как
var myFilter = BehaviorRelay<[MyFilterModel]>(value: [MyFilterModel(data: "{:}")])
но самая большая проблема-это myFilter.value
is только для чтения. Так что, очевидно,
myFilter.value.append(newModel)
это не решение. Я понял, что могу использовать accept
а.
но теперь, когда я пытаюсь проанализировать каждый элемент в ответ и обновить значение myFilter
self?.expertsFilter.accept(newModel)
приведенное выше утверждение дает ошибку quoting
не удается преобразовать значение параметра NewModel в ожидаемый тип аргумента [NewModel]
очевидно, что он ожидает массив, а не отдельный элемент.
решение:
Решение 1:
таким образом, одно решение накапливает весь ответ во временном массиве и после того, как триггерself?.expertsFilter.accept(temporary_array)
решение 2:
если я должен отправить onNext
событие для подписчика при разборе каждого элемента мне нужно скопировать значение self?.expertsFilter в новый массив, добавьте в него вновь проанализированный элемент и верните новый матрица.
решение 3:
избавиться BehaviorRelay
и использовать BehaviorSubject
/PublishSubject
первые два звука удручают, потому что может возникнуть необходимость запускать UI при разборе каждого элемента, я не могу ждать, пока весь ответ будет проанализирован. Поэтому очевидно, что решение 1 не очень полезно.
второе решение намного ужаснее, потому что оно создает новый массив (я знаю его временный и будет выпущен) каждый раз, чтобы отправить onNext событие.
вопрос:
, потому что BehaviorRelay
предлагается в качестве альтернативного Variable
Я в дилемме, я использую accept
правильно?? Есть ли лучший способ решить эту проблему?
пожалуйста, помогите
3 ответов
вы рассматривали просто создание нового массива из существующего значения на ретрансляторе, добавление, а затем вызов accept
?
myFilter.accept(myFilter.value + [newModel])
дом на ответ Далтона, вот удобное расширение:
extension BehaviorRelay where Element: RangeReplaceableCollection {
func acceptAppending(_ element: Element.Element) {
accept(value + [element])
}
}
Я бы сделал что-то подобное -
let requests = PublishSubject<Observable<ServerResponse>>.create()
let responses: Observable<ServerResponse> = requests.switchLatest()
let parsed: Observable<[ParsedItem]> = responses
.flatMap { Observable.from().map { parse() }.toArray() }
parsed.bind(to: ui)
// repeated part
let request1: Observable<ServerResponse> = servive.call()
request.onNext(request1)