Posted at

SwiftUIでElm architectureを実現するフレームワークSelm

SwiftUIにおいてElm architectureを実現するフレームワーク「Selm」を作っています。

Elm architectureと言っても実は私はElmを扱ったことがなくXamarin+F#でのElm architecture実装のFabulousを使った経験から、FabulousのSwift実装のような形で作っています。

Elm architectureはModel-View-Updateというパターンで処理を行います。ビューの状態であるModelをもとにViewを作成し、Updateによりモデルの状態遷移を行います。

Elm architectureはReduxに影響を与えたそうですが、ReSwiftなどのRedux実装と比べてSelmは以下のような特徴を持っています。


  • ディスパッチがタイプセーフで、ReSwiftでいうところのActionをEnumで定義できる。

  • モデル-サブモデル(ビュー-サブビュー)間の関係がモデルとメッセージで記述されるので、ビュー-サブビュー間のやり取りが記述しやすい。


現状

現在WIP Pull Requestを作成しています。

を見てもらえると、雰囲気をつかんでもらえると思います。


実装例

使い方文書から、カウントアップ・ダウンの最小の実装例を抜粋すると以下のようになります。

struct MyView: View {

struct Model {
var count: Int = 0
}

enum Msg {
case up
case down
}

static func initialize() -> (Model, Cmd<Msg>) {
(Model(), Cmd<Msg>.none)
}

static func update(_ msg: Msg, _ model: Model) -> (Model, Cmd<Msg>) {
switch msg {
case .up:
return (model |> set(\.count, model.count + 1), .none)

case .down:
return (model |> set(\.count, model.count - 1), .none)
}
}

@ObjectBinding var driver: Driver<MyView.Msg, MyView.Model>

var body: some View {
Stepper(onIncrement: {
self.driver.dispatch(.up)
}, onDecrement: {
self.driver.dispatch(.down)
}) {
Text(String(self.driver.model.count))
}
}
}


今後について

まだSwiftUIが未成熟なのでSelmの仕様も固まっていません。SwiftUIの更新に合わせてSelmの実装を修正していきます。プロダクトで利用できるように成熟させていければと思っています。

質問があればコメントやGitHub Issueでお願いします。

また、興味を持っていただけて開発に参加していただけるとうれしいです。