Material Motion Exploring solutions that will empower creators with the tools needed to describe and implement rich, interactive motion on any platform. Edit this page · History
MotionObservable ReactiveProperty interactions · ReactiveProperty-createProperty · names
Status Interface level Implementation level Library
Stable as of February 19, 2017 L2: Interaction creator L4: Runtime engineering material-motion
platformsrctests
Android View View
JavaScript View View
iOS (Swift) View View

ReactiveProperty specification

This is the engineering specification for the ReactiveProperty concrete type.

Overview

ReactiveProperty defines an interface for the storage of a generic T value and observation of changes made to it.

Reactive properties can represent existing information. Such properties will write changes to the existing information when the property’s value changes and before notifying observers.

How to create a property

let property = ReactiveProperty(initialValue: 10)

How to change a property’s value

property.value = 100

Observing changes to a property’s value

let subscription = property.subscribe { value in
  print(value)
}

MVP

Expose a concrete ReactiveProperty API

public final class ReactiveProperty<T> {
}

Expose an initializer for anonymous properties

The initializer should accept an initial value. Such properties are called anonymous properties.

class ReactiveProperty<T> {
  public init(initialValue: T)
}

Expose an initializer for external properties

The initializer should accept an initial value and an externalWrite.

class ReactiveProperty<T> {
  public init(initialValue: T, externalWrite: (T) -> Void)
}

Expose a value API

class ReactiveProperty<T> {
  public var value: T
}

Expose a subscribe API

Expose a MotionObserver-shaped subscribe API that accepts a next function.

class ReactiveProperty {
  public func subscribe(next: (T) -> Void) -> Subscription
}

Store a private list of MotionObserver instances

class ReactiveProperty {
  private var observers: [MotionObserver<T>] = []
}

Subscribe adds an observer to a list of observers

class ReactiveProperty {
  func subscribe(next: (T) -> Void) -> Subscription {
    let observer = MotionObserver(next: next)
    observers.append(observer)
    ...
  }
}

Subscribe invokes the observer’s next function with the current value

class ReactiveProperty {
  func subscribe(next: (T) -> Void) -> Subscription {
    ...

    observer.next(value)
  }
}

Changes to value should propagate to all observers

First invoke the externalWrite function and then inform observers of the new value.

class ReactiveProperty {
  public var value: T {
    didSet {
      _externalWrite?(newValue)

      for observer in observers {
        observer.next(newValue)
      }
    }
  }
}

Should be convertible to a MotionObservable

ReactiveProperties should be convertible to a MotionObservable type.

class ReactiveProperty {
  public func asStream() -> MotionObservable<T>
}