Пример архитектуры MVP.стриж - PullRequest
0 голосов
/ 02 февраля 2019

Я хочу изучить классический шаблон архитектуры MVP и для этого попытаться внедрить приложение Weather в Swift.Я теоретически узнал, как это должно работать, но практически застрял на базовом понимании.На данный момент у меня есть модель:

Модель

class WeatherModel: Codable {
    var name: String?
    var main: Main?
}

class Main: Codable {
    var temperature: Float?
    var pressure: Int?
    var humidity: Int?
    private enum CodingKeys: String, CodingKey {
        case temperature = "temp"
        case pressure
        case humidity
    }

Просмотр

final class WeatherViewController: UIViewController {
    @IBOutlet weak var cityTextField: UITextField!
    @IBOutlet weak var temperatureLabel: UILabel!
    @IBOutlet weak var pressureLabel: UILabel!
    @IBOutlet weak var humidityLabel: UILabel!

    private var presenter: WeatherPresenter!

    // MARK: - Lifecycle

    override func viewDidLoad() {
        super.viewDidLoad()
        presenter = WeatherPresenter()
        cityTextField.delegate = self
        presenter.delegate = self

    }

    @IBAction func buttonClicked(_ sender: Any) {
        let city = cityTextField.text
        if let city = city {
            presenter.loadWeatherFor(city: city)
        }
    }
}

extension WeatherViewController: WeatherPresenterProtocol {

    // MARK: - WeatherPresenterProtocol

    func showWeather(data: WeatherModel) {
        if let temperature = data.main?.temperature {
            self.temperatureLabel.text = String(temperature)
        }
        if let pressure = data.main?.pressure {
            self.pressureLabel.text = Constants.pressure + String(pressure)
        }
        if let humidity = data.main?.humidity {
            self.humidityLabel.text = Constants.humidity + String(humidity)
        }
    }
}

Presenter

protocol WeatherPresenterProtocol: class {
    func showWeather(data: WeatherModel) // ?
}

final class WeatherPresenter {
    var model: WeatherModel!
    weak var delegate: WeatherPresenterProtocol?

    func loadWeatherFor(city: String) {
        Network.shared.getWeather(city) { [weak self] (weather, error) in
            DispatchQueue.main.async {
                self?.model = weather
            }
        }
    }
}

В Presenter Я получаю данные от сетевой службы, но не могу понять, как обновить View этими данными (как реализовать протокол в Presenter), потому что View не должен знать о модели, но в моем случае он будет знать (Любая идея реализовать классический MVP будет оценена!

И второй вопрос: как реализовать протокол в Presenter, чтобы получить Model (какэто показано на картинке, которую я взял с https://www.youtube.com/watch?v=qzTeyxIW_ow) enter image description here

Ответы [ 2 ]

0 голосов
/ 03 февраля 2019

Измените

func showWeather(data: WeatherModel)

на

func showWeather(temperature: String, pressure: String, humidity: String)

Переместите конструкцию этих строк из представления в презентатор.Таким образом, представление остается в неведении о модели.

Докладчик не должен напрямую говорить с полным представлением, только с протоколом.

0 голосов
/ 03 февраля 2019

Вы можете попробовать это, в MVP докладчик позаботится об обновлении представления, поэтому измените его, чтобы иметь свойство представления.Здесь представление содержит только экземпляр WeatherController.

В терминах MVP подклассы UIViewController фактически являются представлениями, а не презентаторами.

    class WeatherPresenter : WeatherViewPresenter {
         unowned let view: WeatherView
         let weather: WeatherModel

         required init(view: WeatherView, weather: WeatherModel) {
            self.view = view
            self.weather = weather
         }

        func updateWeatherView() {
           //...update properties on your weather view
           self.view.setTemperature(self.weather.temperature)
        }
    }

Например, чтобы обновить метку температуры, используйте протокол для установки значения температуры.У вас может быть несколько методов для установки нескольких свойств или один для всех ваших элементов пользовательского интерфейса в представлении погоды.

protocol WeatherView: class {
    func setTemperature(temp: String)
    //same for pressure, humid etc
}

Теперь напишите протокол для ведущего погоды

protocol WeatherViewPresenter {
    init(view: WeatherView, weather: WeatherModel)
    func updateWeatherView()
}

Теперь, когда выЕсли у вас есть настройка докладчика для класса погоды, вы можете использовать его как

class WeatherViewController : UIViewController, WeatherView {
    var presenter: WeatherViewPresenter!

    override func viewDidLoad() {
        super.viewDidLoad()
          let model = //your weather model
          presenter = WeatherPresenter(view: self, weather: model)
    }

    func setTemperature(temp: String) {
        self.temperatureLabel.text = temp
    }

}

После получения данных о погоде просто позвоните self.presenter.updateWeatherView(), чтобы обновить вид погоды.

Для получения более подробной информацииинформация, пожалуйста см.

...