LoginSignup
1
2

More than 1 year has passed since last update.

【アーキテクチャ】MVP【Swift】

Last updated at Posted at 2021-05-20

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/

1
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
2