简体   繁体   中英

Simple observable struct with RxSwift?

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.

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)

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