MVPとは?
Model, View, Presenterのこと。
Presenter
ModelとViewを繋ぐ橋渡し役
import Foundation
import UIKit
protocol UserPresenterDelegate: AnyObject {
func presentUsers(users: [User])
func presentAlert(title: String, message: String)
}
typealias PresenterDelegate = UserPresenterDelegate & UIViewController
class UserPresenter {
weak var delegate: PresenterDelegate?
public func getUsers() {
guard let url = URL(string: "https://jsonplaceholder.typicode.com/users") else {
return
}
let task = URLSession.shared.dataTask(with: url) { [weak self] data,_,error in
guard let data = data, error == nil else {
return
}
do {
let users = try JSONDecoder().decode([User].self, from: data)
self?.delegate?.presentUsers(users: users)
}
catch {
print(error)
}
}
task.resume()
}
public func setViewDelegate(delegate: PresenterDelegate) {
self.delegate = delegate
}
public func didTap(user: User) {
delegate?.presentAlert(
title: user.name,
message: "\(user.name) has an email of \(user.name) & a username of \(user.username)")
}
}
Model
アプリのデータ本体、加工、取得、保存などを記載
Presenterから移譲された処理を実行
処理完了後にpresenterに通知
import Foundation
struct User: Codable {
let name: String
let email: String
let username: String
}
View
UIView / UIViewController
Modelとは直接やりとりしない
Presenterにイベントを移譲
Presenterから貰った処理結果をそのまま表示する
import UIKit
class UserViewController: UIViewController, UITableViewDelegate, UITableViewDataSource, UserPresenterDelegate {
private let tableView: UITableView = {
let table = UITableView()
table.register(UITableViewCell.self, forCellReuseIdentifier: "cell")
return table
}()
private var users = [User]()
private let presenter = UserPresenter()
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
title = "Users"
// table
view.addSubview(tableView)
tableView.delegate = self
tableView.dataSource = self
// presenter
presenter.setViewDelegate(delegate: self)
presenter.getUsers()
}
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
tableView.frame = view.bounds
}
// tableview delegate and datasource
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return users.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
cell.textLabel?.text = users[indexPath.row].name
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
// ask presenter to handle the tap
presenter.didTap(user: users[indexPath.row])
}
// presenter delegate
func presentUsers(users: [User]) {
self.users = users
DispatchQueue.main.async {
self.tableView.reloadData()
}
}
func presentAlert(title: String, message: String) {
let alert = UIAlertController(title: title, message: message, preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "Dismiss", style: .cancel, handler: nil))
present(alert, animated: true)
}
}
MVPのメリット
・View と Model の間の依存性がない
・MVVMに比べるとシンプル
MVPのデメリット
・ViewとPresenterの間の依存性が高いという短所
・コード量が増える
参考
https://www.youtube.com/watch?v=SFqIP5jYn_4
https://qiita.com/hicka04/items/25be38a90fdde29c97c2
https://laptrinhx.com/iosapuriakitekucha-bi-jiao-jian-tao-cocoa-mvc-mvvm-mvp-cleanarchtecture-3832902000/