수색…


소개

MVP는 Model-View-Controller의 파생물 인 아키텍처 패턴입니다. 모델, 뷰 및 발표자의 세 가지 구성 요소로 표현됩니다. 자동화 된 단위 테스트를 용이하게하고 프리젠 테이션 논리에서 관심사의 분리를 개선하도록 설계되었습니다.

예제에서는 MVP 패턴을 염두에두고 작성된 간단한 프로젝트를 찾을 수 있습니다.

비고

구성 요소 :

여기에 이미지 설명을 입력하십시오.

  • 모델 은 도메인 데이터 (GUI에서 표시되거나 달리 작동되는)
  • View 는 프리젠 테이션 레이어 (GUI)를 담당합니다.
  • Presenter 는 Model과 View 사이의 "중간 사람"입니다. 뷰에서 수행 된 사용자의 액션에 반응하여 모델에서 데이터를 검색하고 뷰에 표시하기 위해 포맷합니다.

구성 요소 의무 :

모델 전망 증여자
DB 계층과 통신 데이터를 렌더링합니다. 모델에 대한 쿼리를 수행합니다.
적절한 행사 마련 이벤트 수신 모델의 데이터 형식 지정
매우 기본적인 검증 로직 형식화 된 데이터를보기로 보냅니다.
복잡한 검증 로직

MVC와 MVP의 차이점 :

  • MVC의 뷰는 컨트롤러와 밀접하게 결합되어 있으며 MVP의 뷰 부분은 UIView와 UIViewController로 구성됩니다.
  • MVP View는 가능한 한 바보 같으며 (MVVM에서와 같이) 거의 로직을 포함하지 않습니다. MVC View는 비즈니스 로직을 가지고 있으며 모델을 쿼리 할 수 ​​있습니다.
  • MVP View는 사용자 제스처를 처리하고 Presenter에 대한 상호 작용을 위임합니다. MVC에서는 컨트롤러가 제스처 및 명령을 처리합니다. Model
  • MVP 패턴은 단위 테스트를 고도로 지원합니다. MVC는 제한적으로 지원합니다.
  • MVC 컨트롤러에는 많은 UIKit 종속성이 있습니다. MVP Presenter에는 없음이 있습니다.

장점 :

  • MVP는 ViewView 구성 요소의 일부로 UIViewController를 단순하고 수동적이며 덜 복잡하게 만듭니다.]
  • 비즈니스 로직의 대부분은 멍청한 견해로 인해 캡슐화되어 있습니다. 이는 탁월한 테스트 가능성을 제공합니다. 모의 객체를 도입하여 도메인 부분을 테스트 할 수 있습니다.
  • 분리 된 실체는 머리 속에 보관하기 쉽고, 책임은 명확하게 구분됩니다.

단점

  • 더 많은 코드를 작성합니다.
  • 경험이 부족한 개발자 나 아직 패턴을 사용하지 않는 개발자를위한 장벽

Dog.swift

import Foundation

enum Breed: String {
    case bulldog  = "Bulldog"
    case doberman = "Doberman"
    case labrador = "Labrador"
}

struct Dog {
    let name:  String
    let breed: String
    let age:   Int
}

DoggyView.swift

import Foundation

protocol DoggyView: NSObjectProtocol {
    func startLoading()
    func finishLoading()
    func setDoggies(_ doggies: [DoggyViewData])
    func setEmpty()
}

DoggyService.swift

import Foundation

typealias Result = ([Dog]) -> Void

class DoggyService {

    func deliverDoggies(_ result: @escaping Result) {
        
        let firstDoggy  = Dog(name: "Alfred", breed: Breed.labrador.rawValue, age: 1)
        let secondDoggy = Dog(name: "Vinny",  breed: Breed.doberman.rawValue, age: 5)
        let thirdDoggy  = Dog(name: "Lucky",  breed: Breed.labrador.rawValue, age: 3)

        let delay = DispatchTime.now() + Double(Int64(Double(NSEC_PER_SEC)*2)) / Double(NSEC_PER_SEC)
        
        DispatchQueue.main.asyncAfter(deadline: delay) {
            result([firstDoggy,
                    secondDoggy,
                    thirdDoggy])
        }
    }
}

DoggyPresenter.swift

import Foundation

class DoggyPresenter {

    // MARK: - Private
    fileprivate let dogService: DoggyService
    weak fileprivate var dogView: DoggyView?

    init(dogService: DoggyService){
        self.dogService = dogService
    }

    func attachView(_ attach: Bool, view: DoggyView?) {
        if attach {
            dogView = nil
        } else {
            if let view = view { dogView = view }
        }
    }

    func getDogs(){
        self.dogView?.startLoading()
    
        dogService.deliverDoggies { [weak self] doggies in
            self?.dogView?.finishLoading()
        
        if doggies.count == 0 {
            self?.dogView?.setEmpty()
        } else {
            self?.dogView?.setDoggies(doggies.map {
                return DoggyViewData(name: "\($0.name) \($0.breed)",
                                      age: "\($0.age)")
                })
            }
        }
    }
}

struct DoggyViewData {
    let name: String
    let age:  String
}

DoggyListViewController.swift

import UIKit

class DoggyListViewController: UIViewController, UITableViewDataSource {

    @IBOutlet weak var emptyView: UIView?
    @IBOutlet weak var tableView: UITableView?
    @IBOutlet weak var spinner:   UIActivityIndicatorView?

    fileprivate let dogPresenter = DoggyPresenter(dogService: DoggyService())
    fileprivate var dogsToDisplay = [DoggyViewData]()

    override func viewDidLoad() {
        super.viewDidLoad()
    
        tableView?.dataSource = self
        spinner?.hidesWhenStopped = true
        dogPresenter.attachView(true, view: self)
        dogPresenter.getDogs()
    }

    // MARK: DataSource
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return dogsToDisplay.count
    }

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = UITableViewCell(style: .subtitle, reuseIdentifier: "Cell")
        let userViewData = dogsToDisplay[indexPath.row]
        cell.textLabel?.text = userViewData.name
        cell.detailTextLabel?.text = userViewData.age
        return cell
    }
}

extension DoggyListViewController: DoggyView {

    func startLoading() {
        spinner?.startAnimating()
    }

    func finishLoading() {
        spinner?.stopAnimating()
    }

    func setDoggies(_ doggies: [DoggyViewData]) {
        dogsToDisplay = doggies
        tableView?.isHidden = false
        emptyView?.isHidden = true;
        tableView?.reloadData()
    }

    func setEmpty() {
        tableView?.isHidden = true
        emptyView?.isHidden = false;
    }
}


Modified text is an extract of the original Stack Overflow Documentation
아래 라이선스 CC BY-SA 3.0
와 제휴하지 않음 Stack Overflow