はじめに
年末年始にiOSアプリ開発の勉強をしていて,
MVCモデルについて自分なりの理解ができたので,まとめてみました.
MVCモデルとは
よく見る定義
アプリケーション作成時に用いる設計パターンの1種で,
ソースコードをModel, View, Controllerの3つの役割に分割して開発する手法.
- Model : システムの中でビジネスロジックを担当する
- View : 表示や入出力といった処理をする
- Controller : ユーザーの入力に基づき,ModelとViewを制御する
Viewがアプリの見た目の部分を制御するってのはわかる.
ControllerとModelってなんかわかりにくい.
ビジネスロジックってなんですか...というのが僕の初見の感想です.
勉強してみてしっくりきた例え
難しい概念も,身近なものにうまく例えることで理解できることありますよね.
MVCモデルの理解をするにあたり,しっくりきた例えはレストランです.
MVCモデルの相互作用はレストランでの流れに似ています.
- まず客はウェイターに対して料理を注文します.
- ウェイターは注文があったことをキッチンに伝えます.
- キッチンではシェフが冷蔵庫などから素材を取り出し,
- 注文通りの料理を作ります.
- 完成した料理をウェイターがテーブルに運びます.
- 料理が客の元へと届けられます.
この時,それぞれをこう置き換えてみます.
- レストラン : アプリケーション
- 客 : ユーザー
- テーブル : View
- ウェイター : Controller
- キッチン : Model
- まずUser(客)はController(ウェイター)に対してイベント通知(料理を注文)します.
- Controller(ウェイター)は注文があったことをModel(キッチン)に伝えます.
- Model(キッチン)ではシェフがDataBase(冷蔵庫など)から素材(data)を取り出し,
- モデルで定義されている形に整形します(注文通りの料理を作ります).
- 完成した料理をController(ウェイター)がView(テーブル)に運びます.
- 料理が客の元へと届けられます.
僕の中でかなりしっくりきました.
この例えから
・Viewはユーザに対する表示や入出力部分を扱う役割.
・ModelはDataBaseからデータを取ってきて定義されている形(モデル)に変える役割.
・ControllerはModelとViewの仲介であり,Modelから受け取ったデータをViewに表示させたり,Viewから受け取った入力をModelに伝える役割.
という風に解釈できました.
MVCモデルに基づいたアプリ制作
制作したもの
Swiftを用いたQuizアプリケーション.
プロジェクトの構造
View
swiftを使ったiOSアプリなのでViewはstoryboardを使って作成.
Model
本アプリケーションで使用する問題を格納するクラス.
import Foundation
class Question {
let questionText: String
let answer: Bool
init(text: String, correctAnswer: Bool) {
questionText = text
answer = correctAnswer
}
}
また,今回はデータベースとのリモートにやりとりすることはせず,
Question.classのリストを持つQuestionBankを作成.
import Foundation
class QuestionBank {
var list = [Question]()
init() {
let newQuestion = Question(text: "日本の首都は東京である.", correctAnswer: true)
list.append(newQuestion)
list.append(Question(text: "A slug\'s blood is green.", correctAnswer: true))
}
}
Controller
ここでは,Modelで作られたデータをViewに反映させたり,
Buttonが押されるなどのアクションを検知して処理をするという部分を実装している.
import UIKit
class ViewController: UIViewController {
//Place your instance variables here
let allQuestion = QuestionBank()
var pickedAnswer: Bool = false
var nowQuestionIndex: Int = 0
var score:Int = 0
@IBOutlet weak var questionLabel: UILabel!
@IBOutlet weak var scoreLabel: UILabel!
@IBOutlet var progressBar: UIView!
@IBOutlet weak var progressLabel: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
nextQuestion()
}
@IBAction func answerPressed(_ sender: AnyObject) {
if sender.tag == 1 {
pickedAnswer = true
}
else if sender.tag == 2 {
pickedAnswer = false
}
checkAnswer()
nowQuestionIndex += 1
nextQuestion()
}
func updateUI() {
scoreLabel.text = "score: \(score)"
progressLabel.text = "\(nowQuestionIndex + 1) / 14"
progressBar.frame.size.width = (view.frame.size.width / 14) * CGFloat(nowQuestionIndex + 1)
}
func nextQuestion() {
if nowQuestionIndex <= 13 {
questionLabel.text = allQuestion.list[nowQuestionIndex].questionText
updateUI()
}
else {
let alert = UIAlertController(title: "Awesome", message: "You've finished all the question, do you want to restart question?", preferredStyle: .alert)
let restartAction = UIAlertAction(title: "Restart", style: .default) { (UIAlertAction) in
self.startOver()
}
alert.addAction(restartAction)
self.present(alert, animated: true, completion: nil)
}
}
func checkAnswer() {
let correctAnser = allQuestion.list[nowQuestionIndex].answer
if correctAnser == pickedAnswer {
ProgressHUD.showSuccess("Corredt!")
score += 1
}else {
ProgressHUD.showError("Wrong")
}
}
func startOver() {
nowQuestionIndex = 0
score = 0
nextQuestion()
}
}
まとめ
今回伝えたかったことは,
MVCはレストランに例えるとわかりやすいんじゃないかなーということ
簡単なクイズアプリでMVCモデル開発を感じれましたーということ
最後に調べてて感じたことは,
MVCモデルにこれが絶対という正解はないんじゃねってことでした.