IndefiniteObservable 4.0.0

IndefiniteObservable 4.0.0

测试已测试
Lang语言 SwiftSwift
许可证 Apache 2
发布上次发布2017年4月
SwiftSwift 版本3.0
SPM支持 SPM

Jeff Verkoeyen 维护。



  • Material Motion 作者们

IndefiniteObservable.swift

IndefiniteObservable 是一个没有完成或失败概念的、最小的 Observable 实现。

支持的语言

  • Swift 3

这个库由于大量使用泛型不支持 Objective-C。

安装

使用

导入框架

@import IndefiniteObservable;

您现在将能够访问所有 API。

示例应用/单元测试

运行以下命令以从仓库中获取本地副本,以便通过以下方式访问 Catalog 应用程序:

git clone https://github.com/material-motion/indefinite-observable-swift.git
cd observable-swift
pod install
open IndefiniteObservable.xcworkspace

指南

  1. 如何创建可观察对象
  2. 如何创建同步流
  3. 如何使用 blocks 创建异步流
  4. 如何订阅流
  5. 如何取消订阅流
  6. 如何使用对象创建同步流

如何创建可观察对象

在这个示例中,我们将创建最简单的可观察对象类型:一个值的可观察对象。我们将在所有以下指南中使用这个具体的类型。

final class ValueObserver<T>: Observer {
  typealias Value = T

  init(_ next: @escaping (T) -> Void) {
    self.next = next
  }

  let next: (T) -> Void
}

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

如何创建同步流

let observable = ValueObservable<<#ValueType#>> { observer in
  observer.next(<#value#>)
  return noopDisconnect
}

如何使用 blocks 创建异步流

如果您有一个提供基于 blocks 的观察者注册机制的 API,则可以像这样创建异步流。

let observable = ValueObservable<<#ValueType#>> { observer in
  let someToken = registerSomeCallback { callbackValue in
    observer.next(callbackValue)
  }

  return {
    unregisterCallback(someToken)
  }
}

如何订阅流

observable.subscribe { value in
  print(value)
}

如何取消订阅流

取消订阅将调用可观察对象的断开连接方法。要取消订阅,您必须保留由 `subscribe` 返回的订阅实例的引用。

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

subscription.unsubscribe()

如何使用对象创建同步流

许多 iOS/macOS API 使用委托来实现事件处理。要将委托与流连接起来,您需要创建一个 Producer 类。一个 Producer 会监听事件,例如 didTap,并将这些事件转发到一个 IndefiniteObservable 的观察器。

最终结果

class DragConnection {
  typealias Value = (state: UIGestureRecognizerState, location: CGPoint)

  init(subscribedTo gesture: UIPanGestureRecognizer, observer: ValueObserver<Value>) {
    self.gesture = gesture
    self.observer = observer

    gesture.addTarget(self, action: #selector(didPan))

    // Populate the observer with the current gesture state.
    observer.next(currentValue(for: gesture))
  }

  @objc func didPan(_ gesture: UIPanGestureRecognizer) {
    observer.next(currentValue(for: gesture))
  }

  func currentValue(for gesture: UIPanGestureRecognizer) -> Value {
    return (gesture.state, gesture.location(in: gesture.view!))
  }

  func disconnect() {
    gesture?.removeTarget(self, action: #selector(didPan))
    gesture = nil
  }

  var gesture: (UIPanGestureRecognizer)?
  let observer: ValueObserver<Value>
}

let pan = UIPanGestureRecognizer()
view.addGestureRecognizer(pan)

let dragStream = ValueObservable<DragConnection.Value> { observer in
  return DragConnection(subscribedTo: pan, observer: observer).disconnect
}
let subscription = dragStream.subscribe {
  dump($0.state)
  dump($0.location)
}

步骤 1:定义生产者类型

生产者应该是一种订阅类型。

class <#Name#>Producer: Subscription {
}

步骤 2:定义值类型

class DragConnection: Subscription {
  typealias Value = (state: UIGestureRecognizerState, location: CGPoint)
}

步骤 3:实现初始化器

您的初始化器必须接受并存储一个 ValueObserver<Value> 实例。

  init(subscribedTo gesture: UIPanGestureRecognizer, observer: ValueObserver<Value>) {
    self.gesture = gesture
    self.observer = observer
  }

  var gesture: (UIPanGestureRecognizer)?
  let observer: ValueObserver<Value>

步骤 4:连接到事件源并向观察器发送值

  init(subscribedTo gesture: UIPanGestureRecognizer, observer: ValueObserver<Value>) {
    ...

    gesture.addTarget(self, action: #selector(didPan))
  }

  @objc func didPan(_ gesture: UIPanGestureRecognizer) {
    observer.next(currentValue(for: gesture))
  }

  func currentValue(for gesture: UIPanGestureRecognizer) -> Value {
    return (gesture.state, gesture.location(in: gesture.view!))
  }

步骤 5:实现断开连接

您负责在此处断开连接并释放任何资源。

  func disconnect() {
    gesture?.removeTarget(self, action: #selector(didPan))
    gesture = nil
  }

步骤 6:(可选)提供初始状态

通常在注册时向观察器提供当前状态是有帮助的。

  init(subscribedTo gesture: UIPanGestureRecognizer, observer: ValueObserver<Value>) {
    ...

    // Populate the observer with the current gesture state.
    observer.next(currentValue(for: gesture))
  }

步骤 7:观察生产者

let dragStream = ValueObservable<DragConnection.Value> { observer in
  return DragConnection(subscribedTo: pan, observer: observer).disconnect
}
let subscription = dragStream.subscribe {
  dump($0)
}

贡献

此库旨在成为最小的实现,永远不增长。因此,我们只鼓励以文档、测试和示例的形式做出贡献。

了解有关 我们的团队我们的社区 和我们 贡献者基础 的更多信息。

许可

基于 Apache 2.0 许可协议。详情请参阅 LICENSE。