Как презентер в архитектуре VIPER/MVP получает данные?

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

Ответ

Презентер получает готовые доменные модели от Интерактора (в VIPER) или Репоизтория/Сервиса (в MVP). Передача данных происходит асинхронно через:

  1. Замыкания (Closures) — наиболее распространенный способ.
  2. Протоколы/Делегаты — для более строгой связи.
  3. Реактивные потоки (Combine/RxSwift) — для потоковой передачи данных.

Пример с замыканием:

protocol DataServiceProtocol {
    func fetchUserProfile(completion: @escaping (Result<UserProfile, Error>) -> Void)
}

class ProfilePresenter {
    private let service: DataServiceProtocol
    weak var view: ProfileViewProtocol?

    init(service: DataServiceProtocol) {
        self.service = service
    }

    func viewDidLoad() {
        service.fetchUserProfile { [weak self] result in
            // Обработка результата в главном потоке
            DispatchQueue.main.async {
                switch result {
                case .success(let profile):
                    self?.view?.displayProfile(profile)
                case .failure(let error):
                    self?.view?.displayError(error)
                }
            }
        }
    }
}

Ключевой принцип: Презентер никогда не обращается напрямую к сетевому слою или базе данных. Он запрашивает данные у абстракции (протокола), что обеспечивает тестируемость и соблюдение Single Responsibility Principle.