iOSプログラミングにおけるMVC

色々と混乱するのでとりあえずメモ。
文中では、〜だ。と言い切ってるけど正直ちゃんと分かっていない。

関心の分離 - Wikipedia
なるべく機能を分離することで、リファクタリングが楽になる。
(何か修正をしようとしたときに、修正が一カ所で済むということ)

で、MVC
Model View Controller - Wikipedia
プログラムをModel, View,およびそれらを司るControllerに分離する。

上の記事の、参照関係の図が分かりやすい。

まず出力。
ViewはModelへの参照をもつ。ViewがModelしらないと描画できないからね。

ModelとViewの関係は1対多であることが多い(データは1つなのに対して、それを表示するグラフが複数種類ありえることが良い例)
なので、Model側は複数のViewへの参照を持つ必要がある。
で、Modelに何らかの変更がされたときに、Viewに対し「変更されましたよ」という通知(notify)を送る。(Observerパターン)
Viewはその通知を受け取って、更新(再描画)する。
基本的には、Modelが直接Viewを変更するようなことをしない。Viewが自分のことは自分でやるのが基本。

つぎに入力。
基本的に入力はControllerが受け取る。その情報をControllerが整理して、Modelの変更をする。
ただし、入力値の妥当性チェックだとか、1つの値を変更することで波及して他の値も変更されるとか、そういう複雑な処理はModel自身に行わせるように設計する。

ControllerからViewを変更することもある。

ここまでの例をあげると、例えばグラフを表示するようなので、キーボードで数字打つとデータを変更できるとする。
まずデータがModel。で、それを表示させるViewが、円グラフと棒グラフで二つある。
Controllerはキーボードからの入力を受け取って、それを元にデータを変更できる。(C -> M)
最も好き勝手に変更できるわけじゃないので、あくまでControllerは受け取ったデータを元にModelにメッセージを送るだけで、
Model側でちゃんとそのデータの妥当性とかチェックして、変更する。
変更したら、Viewに変更通知が行く(M -> V)。Viewは通知をもらったら再描画(V -> Mの参照)。
キーボードのTabを押したときだけ、円と棒のViewを切り替える(C -> V)みたいな感じかなあ。

なんだけど、一般的に入力って、Viewに向かってする事が多い。
だからViewがその入力イベントを受け取るような形はよくある。
特にiPhoneアプリなんかは多い。なんたって画面に直接タップだからね。
なので、Viewに何か入力があった時、それをControllerに通知する(V -> C)
そのために、ControllerはViewを作る時に、イベントの送り先として自分を登録しておく。(iOSプログラミングではdelegateとして登録することが多いようだ)

まとめると、

  • View -> Model (参照のみ。データとって来て描画する。変更とかはしない。)
  • Model -> Views (変更を通知。典型的にはObserverパターンを使った間接参照)
  • View -> Controller (Viewが受け取った入力イベントをControllerに投げる)
  • Controller -> Models (データの変更要求をするが、値の妥当性チェックだとかその他諸々はModelにまかせる。Fat Modelの原則)
  • Controller -> Views

ところでControllerの単位はどうするかなんだけど、iPhoneアプリでは基本1画面1個。Viewと密接にくっつくので、名前もViewControllerになっている。