RxSwift: управление обновлениями объектов в приложении - PullRequest
0 голосов
/ 14 сентября 2018

Меня очень беспокоит, как управлять изменениями свойств объекта.

Представьте, что у меня есть класс "автомобиль", с некоторыми свойствами, такими как "имя", "дата", "цена" и т. Д.

В моем представлении «А» я показываю все машины, которые я получаю из API. В представлении B & C я могу отображать и редактировать конкретную информацию об автомобиле, выбранном в представлении A (скажем, это «автомобиль AAA»). Также возможно обновить объект car с помощью вызова API для получения последней информации об автомобиле.

Я хочу иметь возможность обновить представление A, если пользователь делает что-то на объекте автомобиля в другом представлении. Или, если пользователь «обновил» объект автомобиля, чтобы быть уверенным, что последние данные об этом автомобиле. Но если пользователь только что изменил название автомобиля, я не хочу обновлять весь пользовательский интерфейс в представлении A только для этого ... Я хочу знать, что изменилось только имя.

Какой лучший способ поймать любое обновление для этого автомобиля в представлении А? Нужно ли иметь класс, который управляет всеми свойствами автомобиля как «PublishRelay» или «PublishSubject», и играть с этим в моем полном приложении?

1 Ответ

0 голосов
/ 14 сентября 2018

Меня беспокоит, как управлять изменениями свойств объекта.

Имейте в виду, что ReactiveX - это функциональная парадигма. Свойства объектов не меняются. Скорее новый объект излучается из наблюдаемой с другими свойствами.

Если вас интересует только отслеживание названия конкретного автомобиля, тогда это простое сопоставление:

extension ObservableType where E == [Car] {
    func nameOfCar(withID id: Int) -> Observable<String?> {
        return map { $0.first(where: { $0.id == id }) }
            .map { $0?.name }
            .distinctUntilChanged()
    }
}

Из-за оператора distinctUntilChanged() приведенное выше значение будет выдавать значение только в случае изменения автомобиля с введенным именем. Опционально есть опция, так что потребитель может определить, нет ли автомобиля в массиве. С технической точки зрения, этот оператор наблюдает за потоком, который испускает массивы автомобилей, отображает карты каждого испускаемого массива, чтобы увидеть, существует ли автомобиль с правильным идентификатором, и, если это так, находит имя этого автомобиля. Затем он сравнивает это имя с предыдущим именем, которое он издает, и выдает имя только в том случае, если оно отличается.

Вы можете наблюдать за объектами автомобилей в целом с помощью:

extension ObservableType where E == Car {
    var name: Observable<String> {
        return map { $0.name }
            .distinctUntilChanged()
    }

    var price: Observable<Double> {
        return map { $0.price }
            .distinctUntilChanged()
    }

    // etc...
}

extension ObservableType where E == [Car] {
    func car(withID id: Int) -> Observable<Car?> {
        return map { $0.first(where: { $0.id == id }) }
            .distinctUntilChanged() // assumes a Car is Equatable
    }
}

Я ожидаю, что с новой системой ключей Swift можно будет найти более общее решение.

...