MVP 패턴 기본구조
#1 심플한 MVP 예제
#1 Diagram
+----------------+ +----------------+ +---------------+
| | fetch | | update | |
| Model | ------> | Presenter | <------ | View |
| (UserProfile) | ^ | (UserDetails) | | | (ProfileUI) |
+----------------+ | +----------------+ | +---------------+
| ^ |
| | |
+-------------+-------------+
saveProfile()
#1 View
import UIKit
protocol ProfileViewProtocol: AnyObject {
func displayUpdateResult(success: Bool)
}
class ProfileViewController: UIViewController, ProfileViewProtocol {
var presenter: ProfilePresenterProtocol!
func onUpdateButtonTapped() {
let profile = UserProfile(
name: "nameTextField.text",
email: "emailTextField.text"
)
presenter.updateProfile(profile)
}
func displayUpdateResult(success: Bool) {
}
}
#1 Presenter
import Foundation
protocol ProfilePresenterProtocol {
func updateProfile(_ profile: UserProfile)
}
class ProfilePresenter: ProfilePresenterProtocol {
weak var view: ProfileViewProtocol?
var model: ProfileModelProtocol
init(view: ProfileViewProtocol, model: ProfileModelProtocol) {
self.view = view
self.model = model
}
func updateProfile(_ profile: UserProfile) {
let success = model.updateProfile(profile)
view?.displayUpdateResult(success: success)
}
}
#1 Model
import Foundation
struct UserProfile {
var name: String
var email: String
}
protocol ProfileModelProtocol {
func updateProfile(_ profile: UserProfile) -> Bool
}
class ProfileModel: ProfileModelProtocol {
func updateProfile(_ profile: UserProfile) -> Bool {
}
}
#2 옵저버 패턴을 이용해 View가 Model을 감시하고 있는 경우 (프리젠테이션 경유)
#2 Diagram
+--------------------+
| |
| UserProfileView |
| (UserProfileVC) |
| |
+---------^----------+
|
| updates UI
|
+------------+-----------+ +-------------------+
| | | |
| UserProfilePresenter +--->+ UserProfileModel |
| | | |
+------------+-----------+ +---------^---------+
^ |
| observes changes |
| | notifies changes
| |
+---------------------------+
#2 View
import UIKit
protocol UserProfileViewProtocol: AnyObject {
func displayUserProfile(_ userProfile: UserProfile)
}
class UserProfileViewController: UIViewController, UserProfileViewProtocol {
var presenter: UserProfilePresenter!
func displayUserProfile(_ userProfile: UserProfile) {
}
@IBAction func nameChanged(_ sender: UITextField) {
presenter.updateName(sender.text ?? "")
}
@IBAction func emailChanged(_ sender: UITextField) {
presenter.updateEmail(sender.text ?? "")
}
}
#2 Model
import Foundation
class UserProfile {
var name: String {
didSet {
notifyObservers()
}
}
var email: String {
didSet {
notifyObservers()
}
}
private var observers = [UserProfileObserver]()
init(name: String, email: String) {
self.name = name
self.email = email
}
func addObserver(_ observer: UserProfileObserver) {
observers.append(observer)
}
private func notifyObservers() {
observers.forEach { $0.userProfileDidChange(self) }
}
}
protocol UserProfileObserver {
func userProfileDidChange(_ userProfile: UserProfile)
}
#2 Presenter
import Foundation
class UserProfilePresenter {
private let model: UserProfile
private weak var view: UserProfileViewProtocol?
init(model: UserProfile, view: UserProfileViewProtocol) {
self.model = model
self.view = view
model.addObserver(self)
}
func updateName(_ name: String) {
model.name = name
}
func updateEmail(_ email: String) {
model.email = email
}
}
extension UserProfilePresenter: UserProfileObserver {
func userProfileDidChange(_ userProfile: UserProfile) {
view?.displayUserProfile(userProfile)
}
}