简体   繁体   中英

RxSwift: How to use shareReplay to lazily get subscription

So I want to be able to lazily subscribe to shared data without it persisting when nobody is subscribed. Then if someone subscribes again, a new observable will be created. I would use a Variable, but I don't want it to persist if no one is subscribed (because if I were using arrays or something larger than an int I don't want to keep them in memory). My current implementation works, except when resubscribing it still gets the last value, which means the value is still persisted. I'm thinking of setting the observable to nil, but I don't know where to do that. Can anyone help me complete this? The code below shows it mostly working, but it looks like the data is sticking around when no one is subscribed.

    var switchTwoDisposable: Disposable? = nil
​    
    @IBAction func switchOneChanged(sender: UISwitch) {
        if sender.on {
            self.switchOneDisposable = currentNumber().subscribeNext { (value) in
            log.debug("Switch 1: \(value)")
        }
      } else {
        switchOneDisposable?.dispose()
      }
    }
    ​
    @IBAction func switchTwoChanged(sender: UISwitch) {
      if sender.on {
        self.switchTwoDisposable = currentNumber().subscribeNext { (value) in
          log.debug("Switch 2: \(value)")
        }
      } else {
        switchTwoDisposable?.dispose()
      }
    }
    ​
    var numberObservable: Observable<Int>? = nil
    ​
    func currentNumber() -> Observable<Int> {
      if let number = numberObservable {
        return number
      }
      self.numberObservable = Observable<Int>.interval(5.0, scheduler: MainScheduler.instance).shareReplay(1)
      return self.numberObservable!
    }
    ​
    ​
    // Switch 1 turned on
    // logs "Switch 1: 0"
    // logs "Switch 1: 1"
    // Switch 2 turned on
    // immediately logs "Switch 2: 1"
    // logs "Switch 1: 2"
    // logs "Switch 2: 2"
    // Switch 1 turned off
    // logs "Switch 2: 3"
    // Switch 2 turned off
    // nothing happens here until we take action again
    // Switch 1 turned on
    // logs "Switch 1: 3"
    // logs "Switch 1: 0"

I finally found the convenient method that does exactly what I need. shareReplayLatestWhileConnected() on an observable will replay the latest value to the 2nd, 3rd, 4th, etc. subscribers, but when everyone unsubscribes, then the last value is not retained.

From the example above replace this line:

self.numberObservable = Observable<Int>.interval(5.0, scheduler: MainScheduler.instance).shareReplay(1)

...with this line:

self.numberObservable = Observable<Int>.interval(5.0, scheduler: MainScheduler.instance).shareReplayLatestWhileConnected()

Update

In my case, I specifically want to get a value from disk (eg Core data or NSUserDefaults) and then if someone updates that value, they can post to a notification that I'll observe with rx_notification . Therefore, in order for this lazy loading to truly work, I would also want an initial value. Therefore it would be helpful to use startWith in this case, where the value given to startWith is the current value on disk. So the code would be analogous to:

Observable<Int>.interval(5.0, scheduler: MainScheduler.instance).startWith(100).shareReplayLatestWhileConnected()

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM