[MVVM] kickstarter/ios-oss での画面遷移のやり方

# MVVM の画面遷移

最近 MVVM を始めたのですが、画面遷移の方法やそれに伴うパラメータの引渡し方法をどうすべきかというのを考えていて、 [kickstarter/ios\-oss](https://github.com/kickstarter/ios-oss) の方法がわかりやすいと思ったので紹介します。

## 忙しい人のための3行まとめ

1. 遷移元の画面遷移ボタンがタップされたら ViewModel にイベントを伝る
2. ViewModel が次の画面に渡すパラメータをセットする
3. View が遷移先の ViewController にパラメータを渡し、画面を開く

# 実際の処理を追う

Signup 画面の Help ボタンから HelpWebView に移動する流れです。

## 1. 遷移元の画面遷移ボタンがタップされたら ViewModel にイベントを伝る

[SignupViewController#L214](https://github.com/kickstarter/ios-oss/blob/2197850f037d08405ceec224676048453a8f36f8/Kickstarter-iOS/Views/Controllers/SignupViewController.swift#L214):

```swift
    helpVM?.inputs.helpTypeButtonTapped(helpType)
```

## 2. ViewModel が次の画面に渡すパラメータをセットする

[HelpViewModel#L83](https://github.com/kickstarter/ios-oss/blob/1cedb98f96ebae1f0ffb5f6a0f65881051ffca44/Library/ViewModels/HelpViewModel.swift#L83):

```swift
    self.showWebHelp = helpTypeTapped
      .filter { $0 != .contact }
```

## 3. View が遷移先の ViewController にパラメータを渡し、画面を開く

[SignupViewController#L144](https://github.com/kickstarter/ios-oss/blob/2197850f037d08405ceec224676048453a8f36f8/Kickstarter-iOS/Views/Controllers/SignupViewController.swift#L144):

```swift
  self.helpViewModel.outputs.showWebHelp
    .observeForControllerAction()
    .observeValues { [weak self] helpType in
      self?.goToHelpType(helpType)
  }
```

[SignupViewController#L203](https://github.com/kickstarter/ios-oss/blob/2197850f037d08405ceec224676048453a8f36f8/Kickstarter-iOS/Views/Controllers/SignupViewController.swift#L203):

```swift
  fileprivate func goToHelpType(_ helpType: HelpType) {
    let vc = HelpWebViewController.configuredWith(helpType: helpType)
    self.navigationController?.pushViewController(vc, animated: true)
  }
```

[HelpWebViewController#L8](https://github.com/kickstarter/ios-oss/blob/1cedb98f96ebae1f0ffb5f6a0f65881051ffca44/Kickstarter-iOS/Views/Controllers/HelpWebViewController.swift#L8):

```swift
  fileprivate let viewModel: HelpWebViewModelType = HelpWebViewModel()

  internal static func configuredWith(helpType: HelpType) -> HelpWebViewController {
    let vc = Storyboard.Help.instantiate(HelpWebViewController.self)
    vc.viewModel.inputs.configureWith(helpType: helpType)
    return vc
  }
```

[HelpWebViewModel#L39](https://github.com/kickstarter/ios-oss/blob/1cedb98f96ebae1f0ffb5f6a0f65881051ffca44/Kickstarter-iOS/ViewModels/HelpWebViewModel.swift#L39):

```swift
  func configureWith(helpType: HelpType) {
    self.helpTypeProperty.value = helpType
  }
```

# まとめ

シンプルでわかりやすいですね :smiley: 
MVVM で画面遷移をするとき、View でやるのか ViewModel でやるのか、パラメータはどう渡すべきか迷っていたのですがこのコードを見てだいぶスッキリしました。

enum の使い方も参考になるところがあり、コードを読むと色々勉強になりそうです :pencil: 
[KickStarter iOSアプリのStoryboardのenumでの管理のしかたに感動した \- Qiita](http://qiita.com/keisei_1092/items/12230bb7ff9106224292)

# おまけ

## 遷移先から遷移前にパラメータを渡したい場合は？

Notification を使うのがいいと思います。
kickstarter のサンプルでは遷移先から遷移前にパラメータを渡す箇所がどこかわからず軽くしか見れていませんが、ソースを `Notification` で検索するとかなり出てきますので、おそらくそうやっていると思われます。
(違ったら教えて欲しい :pray: )

## 他の画面遷移方法

Coordinator を使う方法もアーキテクチャとしては良さそうなのですが、まだ初学者なので登場人物がなるべく少ない状態でやりたいと考えていて、慣れてきたらその方法も検討してみたいです :eyes: 

[画面遷移をVC外で管理するパターンの参考資料 \- Qiita](http://qiita.com/yoching/items/e24197a38cccbba880c1)