Simple observable struct with RxSwift?

2019-02-20 18:55发布

I'm trying to come up with a simple observable object in Swift and thought to use RxSwift. I couldn't find a simple example to do something like this:

protocol PropertyObservable {
  typealias PropertyType
  var propertyChanged: Event<(PropertyType, Any)> { get }
}

class Car: PropertyObservable {
  typealias PropertyType = CarProperty
  let propertyChanged = Event<(CarProperty, Any)>()

  dynamic var miles: Int = 0 {
    didSet {
      propertyChanged.raise(.Miles, oldValue as Any)
    }
  }

  dynamic var name: String = "Turbo" {
    didSet {
      propertyChanged.raise(.Name, oldValue as Any)
    }
  }
}

The above is pure Swift solution for observables from this blog post; I really like how it's a protocol-based solution and not invasive. In my case, I have an object in my project where each property is set asynchronously under the hood (bluetooth device). So I need to observe/subscribe to the changes instead of getting/setting the properties in real-time.

I keep hearing RxSwift will do just that and more. However, I can't find a simple example to match above and beginning to think RxSwift is overkill for my need? Thanks for any help.

1条回答
三岁会撩人
2楼-- · 2019-02-20 19:40

Easiest way to quickly make this observable with RxSwift would probably be to use the RxSwift class Variable (all code here is untested off the top of my head):

import RxSwift

class Car {

  var miles = Variable<Int>(0)

  var name = Variable<String>("Turbo")

}

This enables you to observe the values by subscribing to them:

let disposeBag = DisposeBag()
let car = Car
car.name.asObservable()
  .subscribeNext { name in print("Car name changed to \(name)") }
  .addToDisposeBag(disposeBag) // Make sure the subscription disappears at some point.

Now you've lost the old value in each event. There are of course numerous ways to solve this, the RxSwifty way would probably be to add a scan operation to your element sequence, which works a lot like reduce does on a normal Array:

car.name.asObservable()
  .scan(seed: ("", car.name.value)) { (lastEvent, newElement) in
    let (_, oldElement) = lastEvent
    return (oldElement, newElement)
  }
  .subscribeNext { (old, new) in print("Car name changed from \(old) to \(new)") }
  .addToDisposeBag(disposeBag)
查看更多
登录 后发表回答