【iOS・設計】MVCアーキテクチャ【サンプルコード付き】
公開日:
はじめに
今回は、iOS アプリ開発においてとても大切な設計の中の、MVC アーキテクチャというものについて解説していきます。
アーキテクチャって何?
ていうかたはよかったら下の記事を読んでみてください。
https://www.yukendev.com/blogs/book-ios-architecture
MVC アーキテクチャとは
MVC アーキテクチャは
関心を UI の描画処理(View)とそれ以外のロジック(Model)に分ける
という考えをもとにした GUI アーキテクチャの一つで、GUI アーキテクチャの元祖とも言えるアーキテクチャです。そして、その考えを iOS アプリに持ち込んだのものをCocoa MVCと言います。なので、この記事で解説するのは正確にいうとCocoa MVCになります。以下、『Cocoa MVC』を『MVC』と表記することにします。
MVC では、
- 入力 -> Controller
- 出力 -> View
- データの処理 -> Model
という風に定義します。これらの頭文字を取って**MVC(Model-View-Controller)**と呼ばれているわけです。MVC の考え方を簡潔にまとめると下の図のようになります。
MVC の大きな特徴であるのが、Model
と View
が独立しているということ。View
と Model
の間に Controller が入り、Controller
が View
と Model
を保持することでこれを実現しています。
これにより、View
と Model
の再利用性が高くなるのが大きなメリットです。しかし、Controller
が View
と Model
を保持するため、Controller クラスが肥大化しがちなのが問題点(Fat View Controller
)になりがちです。まとめると、
- Model: 各種ビジネスロジックのかたまり
- View: 画面の描画を担当
- Controller: Model オブジェクトと View オブジェクトを保持し、お互いの架け橋になる
メリット: View と Model の再利用性が高くなる
Controller クラスが肥大化しがち
MVC の概要は以上です。
サンプルアプリ
以上の MVC の考え方を踏まえて、数をラベルに表示し、プラス・マイナスボタンで数を+1, -1 し、5 の倍数の時にはラベルの色を赤くするという簡単なサンプルアプリを作ってみました。
ソースコード
https://github.com/yukendev/sampleMVC
import UIKit
// MARK: -- Controller
class ViewController: UIViewController {
// ControllerがViewを保持
@IBOutlet weak var countLabel: UILabel!
// ControllerがModelを保持
var model: Model? {
didSet { registerModel() }
}
override func viewDidLoad() {
super.viewDidLoad()
model = Model()
}
private func registerModel() {
guard let model = model else { return }
// Modelの値をControllerが監視
model.notificationCenter.addObserver(forName: .init(rawValue: "count"),
object: nil,
queue: nil) { notification in
if let count = notification.userInfo?["count"] as? Int {
// Viewの描画を更新
self.countLabel.text = "\(count)"
if count % 5 == 0 && count != 0 {
self.countLabel.textColor = .red
} else {
self.countLabel.textColor = .black
}
}
}
}
// View -> Controller -> Modelに処理を依頼
@IBAction func minus(_ sender: Any) { model?.minus() }
@IBAction func plus(_ sender: Any) { model?.plus() }
}
import Foundation
// MARK: -- Model
final class Model {
private(set) var count: Int = 0 {
didSet {
notificationCenter.post(name: .init(rawValue: "count"), object: nil, userInfo: ["count": count])
}
}
let notificationCenter: NotificationCenter = NotificationCenter()
func plus() { count += 1 }
func minus() { count -= 1 }
}
『View と Model が独立している』、『Controller が View と Model の橋渡し役』ということを意識して作りました。このアプリでは、Model
がcountという変数を保持し NotificationCenter
を使用することで、Controller
が Model
の count を監視する状態を実装しています。また、今回は StoryBoard を用いて作ったので UILabel
, UIButton
のようなパーツ 1 つ 1 つが MVC の View
に当たるのかなと思いました。とても簡単なアプリなので MVC の考えを理解しやすいのではないでしょうか。
最後に
今回はMVC アーキテクチャについて解説しました。しかし、アーキテクチャはあくまで考え方、概念であって、必ずしも正解があるわけではありません。実装したい機能や、チームの考え方によって内容は変わってくると思います。この記事はあくまでその 1 例として読んでいただけたら幸いです。また、間違いや、もっといい方法などがありましたら教えていただけるとありがたいです。
では、Bye