【问题标题】:Changing one property in a variable triggers subcriptions to other properties. RxSwift更改变量中的一个属性会触发对其他属性的订阅。 RxSwift
【发布时间】:2017-04-29 14:55:18
【问题描述】:

我有以下Chat 的属性结构

struct Chat {
    var id = String()
    var gender = String()
    var date = Date()

    init() {}
}

在视图控制器中,我声明了一个名为 observablechat 的 Chat 实例,然后我使用 flatmap 运算符尝试并仅观察 observablechatdate 属性的变化。但是,如果我更改性别属性(如图所示),订阅就会被触发。我想知道为什么会这样,以及如何修复此代码,以便订阅只查看 date 属性发生的情况,而不查看其他内容?

class ViewController: UIViewController {

    var observablechat = Variable(Chat())

        observablechat.asObservable()
        .flatMap { (Chat) -> Observable<Date> in
            return Observable.of(Chat.matchDate)
        }.subscribe(onNext: { (r) in
            print(r)
        }).addDisposableTo(disposeBag)


        self.observablechat.value.gender = "male" 
        //triggers subscription above. 
    }
}

【问题讨论】:

  • 你确定idgender默认设置为空字符串有意义吗?

标签: ios swift rxjs system.reactive rx-swift


【解决方案1】:

首先,为什么要flatMap

您只需要distinctUntilChangedmapDebugPrint 只会触发两次:初始设置 + 日期更改一次。查看下面的代码并随时提出问题。

import PlaygroundSupport
import RxSwift

struct Chat {

    var id: String
    var gender: String
    var date: Date

    init(id: String = "", gender: String = "", date: Date = Date(timeIntervalSince1970: 0)) {
        self.id = id
        self.gender = gender
        self.date = date
    }
}

final class YourClass {

    lazy var variableChat: Variable<Chat> = Variable<Chat>(Chat())

    var observableDate: Observable<Date> {
        return variableChat
            .asObservable()
            .distinctUntilChanged({ (chatOld, chatNew) -> Bool in
                return chatOld.date == chatNew.date
            })
            .map({ (chat) -> Date in
                return chat.date
            })
            .shareReplay(1)
    }
}

let value = YourClass()
value.observableDate
    .subscribe(onNext: { (date) in
        debugPrint(date.timeIntervalSince1970)
    })
value.variableChat.value.gender = "male"
value.variableChat.value.date = Date()
value.variableChat.value.gender = "female"
value.variableChat.value.gender = "male"
value.variableChat.value.gender = "female"

附:在 Playground 中运行 RxSwift 的方法:readme

【讨论】:

  • Distinctuntilchanged() ,这就是我所缺少的!老实说,我不太确定我为什么使用平面地图。我猜 map 似乎更实用.. 另外,你为什么使用 shareReplay(1)?我得到重播是为了保持一个缓冲区大小,但是为什么要共享呢? (对不起,如果这是一个愚蠢的问题,我是 rx 的初学者)
  • 让我们想象一下你有一些由 map 组成的 observable。你做了多个订阅。原始 observable 的 shareReplay 映射只会执行一次。如果没有原始 observable 的 shareReplay 地图,将为每个订阅调用...我认为您需要检查它在操场上的工作方式:paste.org.ru/?yndoa0 但要小心,在完全理解之前不要使用它(:
  • 会的!我注意到添加您不熟悉的 rx 代码就像玩火一样。是时候阅读文档了。感谢您的时间和解决方案的人!
  • 这是一个很好的答案。几个 cmets... 你不必在日期对象上调用 timeIntervaleSince1970 因为在 Swift 3 中日期是 Equatable 的,如果你把 map 放在 distinctUntilChanged 之前的日期,你不需要提供一个闭包。此外,您只需要 shareReplay 来获取冷可观察数据。 Variable 已经很热了,即它已经具有 shareReplay 能力。在此处添加 shareReplay 不会造成任何伤害,但根本不会改变行为。
猜你喜欢
  • 2014-11-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-08-19
  • 2017-09-14
  • 1970-01-01
  • 2011-06-30
相关资源
最近更新 更多