В архитектуре MVP (iOS), кто должен удерживать сильную ссылку на Presenter?

«В архитектуре MVP (iOS), кто должен удерживать сильную ссылку на Presenter?» — вопрос из категории Архитектура, который задают на 10% собеседований IOS Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

В канонической реализации MVP (Model-View-Presenter) для iOS сильную ссылку на Presenter держит View (ViewController). Presenter, в свою очередь, держит слабую (weak) ссылку на View для предотвращения цикла сильных ссылок (retain cycle).

Почему такая схема?

  • View создает и управляет жизненным циклом Presenter. Без сильной ссылки Presenter будет немедленно деаллоцирован.
  • Presenter ссылается на View для обновления UI. Слабая ссылка гарантирует, что если View (например, ViewController) будет уничтожен, Presenter не будет удерживать его в памяти.

Пример реализации на Swift:

// 1. Протокол View с ограничением `AnyObject` для weak-ссылки
protocol MainViewProtocol: AnyObject {
    func updateData(with items: [String])
}

// 2. Presenter со слабой ссылкой на View
class MainPresenter {
    weak var view: MainViewProtocol?
    private let service: DataService

    init(view: MainViewProtocol, service: DataService) {
        self.view = view
        self.service = service
    }

    func loadData() {
        service.fetchItems { [weak self] items in
            self?.view?.updateData(with: items)
        }
    }
}

// 3. ViewController (View) с сильной ссылкой на Presenter
class MainViewController: UIViewController, MainViewProtocol {
    var presenter: MainPresenter! // Сильная ссылка

    override func viewDidLoad() {
        super.viewDidLoad()
        let service = DataService()
        // View создает и хранит Presenter
        presenter = MainPresenter(view: self, service: service)
        presenter.loadData()
    }

    func updateData(with items: [String]) {
        // Обновление UI
    }
}

Ключевой вывод: Жизненный цикл Presenter зависит от View, а не наоборот.