Swift

NotificationCenterとFuture

この記事は落書きです

Future

Futureを使うと簡単になるのではという問題に直面したので、Futureというものを自分で作りながらお勉強しています。

今のところこんな感じのインターフェイスになっています。

class Future<T> {
  init(_ queue: DispatchQueue = default, _ block: @escaping () throws -> T)

  @discardableResult
  func onSucces(_ block: @escaping (T) -> Void) -> Self
  @discardableResult
  func onFailure(_ bloc: @escaping (Error) -> Void) -> Self

  func success(_ value: T)
  func failure(_ error: Error)

  func map<U>(_ transform: @escaping (T) throws -> U) -> Future<U>
  func flatMap<U>(_ transform: @escaping (T) -> Future<U>) -> Future<U>
}

バカなのでPromiseの必要性が分からないため混ざってます。

Notification

上のFutureをもとにNotificationを受けると値が確定するFutureがもらえるものを作りました。

extension NotificationCenter {

  // block: 戻り値がFutureの値となる。
  //        例外が投げられると投げられたエラーでFutureが確定する。
  //        戻り値がnilの時はNotificationの監視を継続する。
  func future<T>(forName name: Notificaion.Name,
                 object: Any?,
                 queue: OperationQueue?,
                 block: @escaping (Notification) throws -> T?) {

    let future = Future<T>()

    weak var token: NSObjectProtocol?
    token = addObserver(forName: name, object: object, queue: queue) { notification in
      do {
        guard let value = try block(notification) else { return }
        future.success(value)
      } catch {
         future.failure(error)
      }
      token.map(self.removeObserver)
   }

   return future
}