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
IndefiniteObservable MotionObservable
Status Interface level Implementation level Library
Stable as of December 4, 2016 L4: Runtime engineering L4: Runtime engineering indefinite-observable
UpdatesCurrent StatusInitiation dateCompletion date
Removed Subscription's automatic unsubscription on dealloc spec. Stable April 27, 2017
Android View View
JavaScript View View
iOS (Swift) View View

IndefiniteObservable specification

This is the engineering specification for the IndefiniteObservable object.

IndefiniteObservable observers include a single channel of information called the next channel.

Observers can be extended to include other channels of information, if required by a given platform. This is most commonly necessary when a platform’s animation system is opaque to the application, such as Core Animation on iOS.


IndefiniteObservable is a minimal implementation of Observable with no concept of completion or failure.


public final class ValueObserver<T>: Observer<T> {
  public init(_ next: (T) -> Void) { = next

  public let next: (T) -> Void

public class ValueObservable<T>: IndefiniteObservable<ValueObserver<T>> {
  public final func subscribe(_ next: (T) -> Void) -> Subscription {
    return super.subscribe(observer: ValueObserver(next))

let observable = ValueObservable<Int> { observer in
  return noopDisconnect

observable.subscribe { value in

// Example operators:
extension ValueObservable {
  public func _operator<U>(_ operation: (ValueObserver<U>, T) -> Void) -> ValueObservable<U> {
    return ValueObservable<U> { observer in
      return self.subscribe(next: observer: ValueObserver<T> {
        operation(observer, $0)

  public func _map<W>(transform: (T) -> U) -> ValueObservable<W> {
    return _operator(op) { observer, value in

  public func _filter(predicate: (T) -> Bool) -> ValueObservable<T> {
    return _operator(op) { observer, value in
      if predicate(value) {


Expose a generic abstract Observer type

Define the base Observer type which has a single channel called next. next accepts an argument of type T.

public protocol Observer<T> {
  func next(value: T)

Expose a concrete IndefiniteObservable type

There is a single generic observer type: O. This is the type of observer that can be provided to the subscribe method. This type should conform to the abstract Observer type.

class IndefiniteObservable<O: Observer> {

Expose a Connect function type

Connect receives an observer and returns a Disconnect function.

public typealias Connect<O> = (O) -> Disconnect

Expose a noopDisconnect constant

This value can be returned by a connect function to indicate that no disconnection work will occur.

public let noopDisconnect: Disconnect = { }

Expose a Disconnect function type

The function signature expected to be returned by a Connect.

public typealias Disconnect = () -> Void

Expose an Unsubscribe function type

Unsubscribe should have the same shape as Disconnect.

public typealias Unsubscribe = () -> Void

Expose a Subscription object type

A representation of a subscription made by invoking subscribe on an IndefiniteObservable.

public final class Subscription {
  init(_ disconnect: () -> Void) {
    self.disconnect = disconnect

  public func unsubscribe() {
    if disconnect != nil {
      disconnect = nil

  private var disconnect: (Disconnect)?

This class should store a disconnect function. The first time unsubscribe is called, it should call the disconnect function. Thereafter, it should do nothing. disconnect shouldn’t be called more than once per connection.

Expose an IndefiniteObservable initializer

Requires a Connect type. Store connect as a private constant.

class IndefiniteObservable<O> {
  public init(connect: Connect<O>) {
    self._connect = connect

  private let _connect: Connect<O>

Expose a subscribe API on IndefiniteObservable

Expose a subscribe API on IndefiniteObservable that accepts an observer and returns a Subscription.

subscribe should invoke self._connect with the provided observer.

class IndefiniteObservable<O> {
  func subscribe(observer: O) -> Subscription {
    return self._connect(observer);