Comment utiliser BehaviorRelay comme alternative à la Variable dans RxSwift?

Comme de RxSwift4, Variable est déplacé à Deprecated.swift marquant la possible dévalorisation de Variable dans l'avenir. Une alternative proposée à VariableBehaviorRelay. En postant cette question, comme je n'ai pas pu trouver beaucoup de tutoriel sur le web en utilisant BehaviorRelay je pose une question aussi fondamentale ici dans SO.

supposons que j'ai un appel webService en cours et que je reçois un morceau de données qui est JSONArray, en analysant un objet JSON un par un, je mets à jour la valeur de ma Variable la propriété

Voici ma déclaration de variable

var myFilter = Variable<[MyFilterModel]>([MyFilterModel(data: "{:}")])

sur l'obtention d'un nouvel élément à chaque fois que je mettrais à jour ma Variable comme

myFilter.value.append(newModel)

comme la Variable était liée à CollectionView, collectionVie mettait à jour son UI immédiatement avec l'objet nouvellement ajouté.

problem with BehaviorRelay

Maintenant ma déclaration ressemble à

var myFilter = BehaviorRelay<[MyFilterModel]>(value: [MyFilterModel(data: "{:}")])

Mais le plus gros problème est myFilter.value est readOnly. Alors, évidemment

myFilter.value.append(newModel) 

n'est pas une solution. J'ai compris que je peux utiliser accept plutôt.

mais maintenant, quand j'essaie d'analyser chaque élément en réponse et mettre à jour la valeur de myFilter

self?.expertsFilter.accept(newModel)

La déclaration ci-dessus donne une erreur en citant

ne peut pas convertir la valeur de NewModel en type d'argument attendu [NewModel]

Évidemment, il attend un tableau et pas un élément individuel.

palliatif:

Solution 1:

ainsi une solution est d'accumuler toute la réponse dans un tableau temporaire et une fois fait déclencher self?.expertsFilter.accept(temporary_array)

Solution 2:

Si je dois envoyer onNext événement à l'abonné sur l'analyse de chaque élément, j'ai besoin de copier la valeur de l'auto?.expertsFilter à new Array, ajouter l'élément nouvellement parsé à elle et retourner le nouveau tableau.

Solution 3:

se débarrasser de BehaviorRelay et utiliser BehaviorSubject/PublishSubject

les deux premiers semblent déprimants, parce qu'il peut y avoir un besoin de déclencher L'UI sur l'analyse de chaque élément Je ne peux pas attendre jusqu'à ce que la réponse entière est analysée. Il est donc évident que la solution1 n'est pas très utile.

la seconde solution est beaucoup plus horrible car elle crée un nouveau tableau (je sais qu'elle est temporaire et qu'elle sera libérée) à chaque fois pour envoyer onNext événement.

Question:

Parce que BehaviorRelay est proposé comme alternative à Variable suis en dilemme, je suis à l'aide de accept correctement?? Est-il un meilleur moyen de le résoudre?

s'il vous Plaît aider

26
demandé sur Sandeep Bhandari 2017-11-23 12:59:19

3 réponses

avez-vous envisagé de créer simplement un nouveau tableau à partir de la valeur existante sur le relais, en ajoutant, puis en appelant accept?

myFilter.accept(myFilter.value + [newModel])
9
répondu daltonclaybrook 2018-05-01 03:36:44

réponse de Dalton, ici est une extension pratique:

extension BehaviorRelay where Element: RangeReplaceableCollection {
    func acceptAppending(_ element: Element.Element) {
        accept(value + [element])
    }
}
3
répondu retendo 2018-08-28 15:15:09

je voudrais faire quelque chose comme ça -

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)
2
répondu Maxim Volgin 2017-11-23 10:15:37