← Назад к вопросам

Что такое Presentation Layer?

1.3 Junior🔥 122 комментариев
#Анимации и графика

Комментарии (2)

🐱
deepseek-v3.2PrepBro AI6 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Что такое Presentation Layer в iOS-разработке?

Presentation Layer (Слой представления, UI-слой) — это архитектурный слой, ответственный за отображение данных пользователю и обработку его взаимодействий с интерфейсом. Его основная цель — отделить бизнес-логику и данные приложения от способа их визуализации и управления. В контексте iOS-разработки, этот слой включает в себя всё, что связано с пользовательским интерфейсом: UIViewController, UIView, а также механизмы управления состоянием, обработки событий и форматирования данных для отображения.

Ключевые обязанности Presentation Layer:

  • Отображение данных: Преобразование моделей данных (из Domain или Business Logic Layer) в удобочитаемый формат (например, форматирование даты, валюты).
  • Обработка пользовательского ввода: Реагирование на действия пользователя (тапы, жесты, ввод текста) и передача соответствующих команд в нижележащие слои (например, в Use Cases или Interactors).
  • Управление жизненным циклом UI: Обработка появления/исчезновения экранов, переходов, анимаций.
  • Валидация ввода (на уровне UI): Проверка корректности данных, введённых в текстовые поля, перед их отправкой в бизнес-логику.

Паттерны и подходы в Presentation Layer

Для структурирования кода в этом слое активно используются паттерны, которые разделяют ответственность внутри самого слоя. Самые распространённые из них:

1. MVC (Model-View-Controller)

Базовый паттерн Apple, где UIViewController часто выступает тяжёлым контроллером, совмещающим логику представления и бизнес-логику (что считается антипаттерном — Massive View Controller).

// Пример "тяжёлого" контроллера в MVC
class ProductViewController: UIViewController {
    @IBOutlet weak var titleLabel: UILabel!
    @IBOutlet weak var priceLabel: UILabel!
    
    var product: Product? // Модель
    
    override func viewDidLoad() {
        super.viewDidLoad()
        titleLabel.text = product?.name
        // Контроллер сам занимается форматированием
        priceLabel.text = String(format: "%.2f руб.", product?.price ?? 0)
        
        // И может содержать сетевые запросы (нарушение слоёв!)
        // NetworkService.shared.fetchProductDetails(...)
    }
    
    @IBAction func buyButtonTapped(_ sender: UIButton) {
        // Контроллер напрямую обращается к логике корзины
        CartManager.shared.add(product: product!)
    }
}

2. MVP (Model-View-Presenter)

Вводит Presenter — объект, который берёт на себя логику представления. View (часто это UIViewController) становится пассивным и только отображает то, что ему передал Presenter.

// Контракт (протокол) для View
protocol ProductViewProtocol: AnyObject {
    func display(title: String)
    func display(price: String)
}

class ProductPresenter {
    private weak var view: ProductViewProtocol?
    private let product: Product
    
    init(view: ProductViewProtocol, product: Product) {
        self.view = view
        self.product = product
    }
    
    func viewDidLoad() {
        // Presenter форматирует данные для View
        view?.display(title: product.name)
        let formattedPrice = NumberFormatter.localizedString(from: NSNumber(value: product.price), number: .currency)
        view?.display(price: formattedPrice)
    }
    
    func buyButtonTapped() {
        // Presenter делегирует бизнес-действие отдельному сервису
        CartService.shared.addToCart(productID: product.id)
    }
}

3. MVVM (Model-View-ViewModel)

Наиболее популярный в современной iOS-разработке паттерн. ViewModel предоставляет данные и команды, уже готовые для привязки к UI. Связь между View и ViewModel часто реализуется через биндинги (например, с помощью Combine или RxSwift) или через механизм наблюдаемых свойств (@Published в Combine).

import Combine

// ViewModel
class ProductViewModel {
    // Наблюдаемые свойства, к которым может привязаться View
    @Published var titleText: String = ""
    @Published var priceText: String = ""
    
    private let product: Product
    private let cartService: CartServiceProtocol
    
    init(product: Product, cartService: CartServiceProtocol = CartService.shared) {
        self.product = product
        self.cartService = cartService
        configureOutputs()
    }
    
    private func configureOutputs() {
        titleText = product.name
        let formatter = NumberFormatter()
        formatter.numberStyle = .currency
        priceText = formatter.string(from: NSNumber(value: product.price)) ?? ""
    }
    
    // Публичный метод для обработки действия пользователя
    func buy() {
        cartService.addToCart(productID: product.id)
    }
}

// View (UIViewController)
class ProductViewController: UIViewController {
    private var viewModel: ProductViewModel
    private var cancellables = Set<AnyCancellable>()
    
    @IBOutlet weak var titleLabel: UILabel!
    @IBOutlet weak var priceLabel: UILabel!
    
    init(viewModel: ProductViewModel) {
        self.viewModel = viewModel
        super.init(nibName: nil, bundle: nil)
    }
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // Привязка данных ViewModel к UI элементам с помощью Combine
        viewModel.$titleText
            .assign(to: \.text, on: titleLabel)
            .store(in: &cancellables)
        
        viewModel.$priceText
            .assign(to: \.text, on: priceLabel)
            .store(in: &cancellables)
    }
    
    @IBAction func buyButtonTapped(_ sender: UIButton) {
        viewModel.buy() // View просто вызывает команду во ViewModel
    }
}

4. VIPER / Clean Architecture

В этих более сложных архитектурах Presentation Layer также чётко выделен и состоит из:

  • View (UIViewController): Пассивно отображает.
  • Presenter / ViewModel: Логика представления, получает данные от Interactor, форматирует их для View.
  • Router: Отвечает за навигацию между модулями.
  • Configurator / Builder: Собирает все компоненты модуля вместе.

Принципы хорошего Presentation Layer:

  • Пассивный View: UI-компоненты должны быть как можно более "глупыми", их задача — только отрисовка и передача событий.
  • Отсутствие бизнес-логики: Слой не должен содержать правил предметной области, сетевых запросов или работы с базой данных.
  • Тестируемость: Основная логика (в Presenter или ViewModel) должна быть легко покрыта модульными тестами без необходимости создания UI.
  • Разделение ответственности: Чёткое следование выбранному паттерну (MVP, MVVM) для избежания Massive View Controller.

Таким образом, Presentation Layer — это критически важный слой, который служит мостом между пользователем и внутренней логикой приложения. Его грамотная организация с использованием современных паттернов (в первую очередь MVVM с реактивным программированием) является ключом к созданию поддерживаемого, тестируемого и отзывчивого iOS-приложения.

Что такое Presentation Layer? | PrepBro