使用Rx-Realm和Rx-Swift的Observable不会停止射击[除非我输入.replay(n)]

时间:2017-02-18 12:05:45

标签: ios swift realm rx-swift

我有以下Realm对象:

class GeolocationObject: Object {

    dynamic var id: String = UUID().uuidString

    dynamic var latitude: Double = 0
    dynamic var longitude: Double = 0

    let addresses = LinkingObjects.init(fromType: AddressObject.self, property: "geolocation")

    override static func primaryKey() -> String? {
        return "id"
    }

}

我也有链接地址对象(为简单起见,我只有一个道路属性):

class AddressObject: Object {

    dynamic public var id: String = UUID().uuidString
    dynamic var road: String = ""
    dynamic var geolocation: GeolocationObject?

    override static func primaryKey() -> String? {
        return "id"
    }

}

正如您所看到的,我与GeolocationObject建立了To-One关系,并且对于我的应用程序的需求,有可能在同一个Geolocation上,我可能有很多AddressObjects。因此,LinkingObjects中有GeolocationObject个属性。

我创建了一个带有RxSwift和RxRealm的反应式抽象层(RealmProvider只提供了一种更简单的Realm写入事务的方法):

class GeolocationViewModel {

    let disposeBag: DisposeBag
    let geolocationObject: GeolocationObject
    let id: String

    var latitude: Variable<Double>
    var longitude: Variable<Double>

    let addresses: Observable<[AddressViewModel]>

    init(geolocationObject: GeolocationObject) {

        self.disposeBag = DisposeBag()
        self.geolocationObject = geolocationObject
        self.id = self.geolocationObject.id

        self.latitude = Variable(self.geolocationObject.latitude)
        self.longitude = Variable(self.geolocationObject.longitude)

        self.addresses =
            Observable.array(from: self.geolocationObject.addresses)
                .map({ $0.flatMap({ AddressViewModel.init(addressObject: $0) }) })    

        self.latitude.asObservable()
            .subscribe(onNext: { [unowned self] (latitude) in
                RealmProvider.commitWrite {
                    self.geolocationObject.latitude = latitude
                }
            })
            .disposed(by: disposeBag)

        self.longitude.asObservable()
            .subscribe(onNext: { [unowned self] (longitude) in
                RealmProvider.commitWrite {
                    self.geolocationObject.longitude = longitude
                }
            })
            .disposed(by: disposeBag)

    }

}

class AddressViewModel {

    let disposeBag: DisposeBag
    let addressObject: AddressObject
    let id: String

    var road: Variable<String>

    var geolocation: Variable<GeolocationViewModel?>

    init(addressObject: AddressObject) {

        self.disposeBag = DisposeBag()
        self.addressObject = addressObject
        self.id = self.addressObject.id

        self.road = Variable(self.addressObject.road)

        if let geolocationObject = self.addressObject.geolocation {
            self.geolocation = Variable(GeolocationViewModel.init(geolocationObject: geolocationObject))
        } else {
            self.geolocation = Variable(nil)
        }

        self.road.asObservable()
            .debug()
            .subscribe(onNext: { [unowned self] (road) in
                RealmProvider.commitWrite {
                    self.addressObject.road = road
                }
            })
            .disposed(by: disposeBag)

        self.geolocation.asObservable()
            .subscribe(onNext: { [unowned self] (geolocationViewModel) in
                RealmProvider.commitWrite {
                    self.addressObject.geolocation = geolocationViewModel?.geolocationObject
                }
            })
            .disposed(by: disposeBag)

}

正如您所看到的,我已将LinkingObjects属性作为Observable传递,因此如果出现更改,系统会通知您。

简而言之,我创建了一个带有地理位置对象的地址。 一切都很好,直到现在。我抓住AddressViewType,然后改变道路(Variable)。如果我通过AddressViewType订阅GeolocationViewType数组,则会正确通知,但会一直触发。

例如:

let geolocationViewModel = GeolocationViewModel(geolocationObject: GeolocationViewModel)
let addressViewModel = AddressViewModel(addressObject: AddressObject())
addressViewModel.road.value = test1
addressViewModel.geolocation.value = geolocationViewModel

geolocationViewModel.addresses.subscribe(onNext: { addressArray in

print(addressArray[0].road) 

})
.disposed(by: disposeBag)

如果我尝试像这样改变addressViewModel的道路:

addressViewModel.road.value = "Test2"

它正确通知print语句并打印。但它随着新价值一直在发射!它不会仅发送一次打印。

我发现如果Observable上地址的GeolocationObject是这样的话,它会停止:

self.addresses =
                Observable.array(from: self.geolocationObject.addresses)
                    .map({ $0.flatMap({ AddressViewModel.init(addressObject: $0) }) })
                    .replay(1)

后来我又添加了.share() 如果我不放.replay(1),为什么它会一直开火? 它不应该只发送一次并停止吗?

0 个答案:

没有答案