39
39

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Swift+有限オートマトンでPromiseを拡張する

Last updated at Posted at 2014-08-27

前回のSwiftで有限オートマトン(ステートマシン)を作る - Qiitaの続きです。

ステートマシン(SwiftState)を実際に使うにあたり、何か分かりやすいサンプルを作った方が良いと思い、今回、JavaScriptでおなじみのPromiseクラスを再発明してみました。

Promiseについて

Promiseについては、こちらの記事が参考になります。

一般的なPromiseライブラリの状態遷移は、Pending => Fulfilled or Rejectedの2パターンがあります。
が、機能としてややシンプルすぎる&n番煎じ感が否めないので、新たにProgressPauseCancelといったインターフェースを追加して、複雑な状態遷移にも耐えられる設計にしてみます。

今回、設計した状態遷移図

RejectCancelは本来、内部処理/外部処理として区別されるべきですが、簡便のため、同じRejected終状態として扱っています)

SwiftStateの使い方

ステートマシンの使い方をざっと眺めてみます。

まず、上記の遷移図から、タスクの「状態」と「遷移イベント」を定義します。


public enum TaskState: StateType
{
    case Paused
    case Running
    case Fulfilled
    case Rejected
    ...
}

public enum TaskEvent: StateEventType
{
    case Pause
    case Resume
    case Progress
    case Fulfill
    case Reject   // also used in cancellation for simplicity
    ...
}

次に、ステートマシンを定義します。

// setup state machine
self.machine = StateMachine<TaskState, TaskEvent>(state: .Running) {
    
    // $0 = machine
    $0.addRouteEvent(.Pause, transitions: [.Running => .Paused])
    $0.addRouteEvent(.Resume, transitions: [.Paused => .Running])
    $0.addRouteEvent(.Progress, transitions: [.Running => .Running])
    $0.addRouteEvent(.Fulfill, transitions: [.Running => .Fulfilled])
    $0.addRouteEvent(.Reject, transitions: [.Running => .Rejected, .Paused => .Rejected])
    
    $0.addEventHandler(.Resume) { context in
        configuration.resume?()
        return
    }
    
    $0.addEventHandler(.Pause) { context in
        configuration.pause?()
        return
    }
    
    ...
}

これにより、self.machineは初期状態.Runningから、イベント遷移(.Pause/.Fulfill/.Reject)を経て別の状態に遷移し、ひとたび終状態(.Fulfilled,.Rejected)になると逆戻りできなくなります(状態遷移のバリデーション用として使えます)。

また、ハンドラは複数登録が可能なので、Promiseのように終状態が確定するまで複数ハンドリングをpendingする際にも、自前で配列を用意せず、ステートマシン側に持たせることができます。これによって、Promise側に持たせるコード量が少しだけ短縮できます。

今回作ったライブラリ

上記をふまえて、今回作ったPromiseライブラリはこちらです:
https://github.com/inamiy/SwiftTask

作成にあたり、PromiseKitやBolts-iOS、その他JavaScriptライブラリなどを参考にしています。
こちらも後日、Qiita記事にまとめていけたらと思うので、StarやPull Request、ツッコミ等あればよろしくお願いします。

39
39
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
39
39

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?