Настройка архитектуры VIPER для iOS-приложения

TRUETECH занимается разработкой, поддержкой и обслуживанием мобильных приложений iOS, Android, PWA. Имеем большой опыт и экспертизу для публикации мобильных приложений в популярные маркеты Google Play, App Store, Amazon, AppGallery и другие.

Разработка и поддержка любых видов мобильных приложений:

Информационные и развлекательные мобильные приложения
Новостные приложения, игры, справочники, онлайн-каталоги, погодные, фитнес и здоровье, туристические, образовательные, социальные сети и мессенджеры, квиз, блоги и подкасты, форумы, агрегаторы
Мобильные приложения электронной коммерции
Интернет-магазины, B2B-приложения, маркетплейсы, онлайн-обменники, кэшбэк-сервисы, биржи, дропшиппинг-платформы, программы лояльности, доставка еды и товаров, платежные системы
Мобильные приложения для управления бизнес-процессами
CRM-системы, ERP-системы, управление проектами, инструменты для команды продаж, учет финансов, управление производством, логистика и доставка, управление персоналом, системы мониторинга данных
Мобильные приложения электронных услуг
Доски объявлений, онлайн-школы, онлайн-кинотеатры, платформы предоставления электронных услуг, платформы кешбека, видеохостинги, тематические порталы, платформы онлайн-бронирования и записи, платформы онлайн-торговли

Это лишь некоторые из типы мобильных приложений, с которыми мы работаем, и каждый из них может иметь свои специфические особенности и функциональность, а также быть адаптированным под конкретные потребности и цели клиента.

Услуги, которые мы предлагаем
Показано 1 из 1Все 1735 услуг
Настройка архитектуры VIPER для iOS-приложения
Сложный
~3-5 дней
Часто задаваемые вопросы

Наши компетенции:

Этапы разработки

Последние работы

  • image_mobile-applications_feedme_467_0.webp
    Разработка мобильного приложения для компании FEEDME
    792
  • image_mobile-applications_xoomer_471_0.webp
    Разработка мобильного приложения для компании XOOMER
    671
  • image_mobile-applications_rhl_428_0.webp
    Разработка мобильного приложения для компании RHL
    1097
  • image_mobile-applications_zippy_411_0.webp
    Разработка мобильного приложения для компании ZIPPY
    969
  • image_mobile-applications_affhome_429_0.webp
    Разработка мобильного приложения для компании Affhome
    914
  • image_mobile-applications_flavors_409_0.webp
    Разработка мобильного приложения для компании FLAVORS
    495

Настройка архитектуры VIPER для iOS-приложения

VIPER — самая детальная из архитектур для iOS. View, Interactor, Presenter, Entity, Router — пять компонентов на один экран. В небольших командах на это смотрят со скепсисом: много файлов, много протоколов, много кода. В командах 5+ человек, работающих над одним UIKit-приложением, VIPER становится конкурентным преимуществом: изолированные модули не конфликтуют в git, Interactor тестируется без UI, Router инкапсулирует навигацию.

Анатомия VIPER-модуля

Один экран = один VIPER-модуль. Для экрана профиля:

ProfileModule/
    ProfileView.swift          // UIViewController, реализует ProfileViewProtocol
    ProfilePresenter.swift     // логика представления, реализует ProfilePresenterProtocol
    ProfileInteractor.swift    // бизнес-логика и работа с данными
    ProfileRouter.swift        // навигация, реализует ProfileRouterProtocol
    ProfileAssembly.swift      // фабрика, собирает модуль и инжектирует зависимости
    Protocols/
        ProfileProtocols.swift // все протоколы модуля в одном файле

Протоколы — основа VIPER:

// View ← Presenter
protocol ProfileViewProtocol: AnyObject {
    func displayUser(_ viewModel: ProfileViewModel)
    func displayError(_ message: String)
    func setLoading(_ loading: Bool)
}

// Presenter ← View
protocol ProfileViewToPresenterProtocol: AnyObject {
    func viewDidLoad()
    func editButtonTapped()
    func settingsTapped()
}

// Presenter ← Interactor
protocol ProfileInteractorOutputProtocol: AnyObject {
    func didFetchUser(_ user: User)
    func didFailFetchUser(_ error: Error)
}

// Interactor ← Presenter
protocol ProfileInteractorInputProtocol: AnyObject {
    func fetchUser()
}

// Router ← Presenter
protocol ProfileRouterProtocol: AnyObject {
    func navigateToEditProfile(user: User)
    func navigateToSettings()
}

Это много кода. Именно поэтому для VIPER создают Xcode-шаблоны или генераторы (Generamba, Vipergen) — один шаблон, команда generate profile создаёт все 7 файлов с базовым кодом.

Interactor — сердце бизнес-логики

Interactor — единственное место, где живёт бизнес-логика. Он не знает о UIKit, не знает о конкретном хранилище:

final class ProfileInteractor {
    weak var presenter: ProfileInteractorOutputProtocol?
    private let userRepository: UserRepositoryProtocol

    init(userRepository: UserRepositoryProtocol) {
        self.userRepository = userRepository
    }
}

extension ProfileInteractor: ProfileInteractorInputProtocol {
    func fetchUser() {
        Task {
            do {
                let user = try await userRepository.fetchCurrentUser()
                await MainActor.run {
                    presenter?.didFetchUser(user)
                }
            } catch {
                await MainActor.run {
                    presenter?.didFailFetchUser(error)
                }
            }
        }
    }
}

Тестирование Interactor: подменяем UserRepositoryProtocol моком — чистый Swift, XCTest без симулятора. Это то, ради чего стоит платить стоимость бойлерплейта.

Presenter: трансформация данных

Presenter получает доменные Entity от Interactor и создаёт ViewModel для View:

extension ProfilePresenter: ProfileInteractorOutputProtocol {
    func didFetchUser(_ user: User) {
        let viewModel = ProfileViewModel(
            displayName: "\(user.firstName) \(user.lastName)",
            avatarURL: user.avatarURL,
            memberSince: DateFormatter.mediumStyle.string(from: user.createdAt),
            isVerified: user.verificationStatus == .verified
        )
        view?.displayUser(viewModel)
        view?.setLoading(false)
    }
}

ProfileViewModel — структура с UI-данными, не доменная User. View получает готовые строки, не занимается форматированием.

Assembly: сборка модуля

Вся инициализация и DI — в Assembly:

enum ProfileAssembly {
    static func build(coordinator: AppCoordinator) -> UIViewController {
        let interactor = ProfileInteractor(
            userRepository: DI.resolve(UserRepositoryProtocol.self)
        )
        let router = ProfileRouter(coordinator: coordinator)
        let presenter = ProfilePresenter(interactor: interactor, router: router)
        let view = ProfileViewController()

        view.presenter = presenter
        presenter.view = view
        interactor.presenter = presenter

        return view
    }
}

Вся граф зависимостей модуля виден в одном файле. При добавлении новой зависимости — только Assembly меняется, остальные компоненты изолированы.

Генераторы кода

Писать VIPER вручную — слишком дорого по времени. Инструменты:

  • Generamba — Ruby gem, шаблоны через YAML, интеграция в Xcode с командой generamba gen ProfileModule viper
  • XcodeGen с кастомными шаблонами
  • Swift Package с Makefile — собственный генератор на основе Stencil-шаблонов

На проектах с 30+ модулями без генератора VIPER превращается в боль.

VIPER vs Clean Architecture + MVVM

VIPER органичен для UIKit + Objective-C legacy или больших команд с устоявшимися процессами. Для новых проектов на SwiftUI Clean Architecture + MVVM + @Observable — чище и без бойлерплейта. Для Flutter — BLoC с Clean Architecture ближе к VIPER по идеологии, но без UIKit-зависимостей.

Выбор в пользу VIPER обоснован, если:

  • Существующий проект уже на VIPER (рефакторить нет смысла)
  • Команда 5+ iOS-разработчиков, активный параллельный код
  • Высокие требования к тестируемости каждого слоя

Что настраиваем

Проектируем протоколы → создаём Xcode-шаблон или настраиваем Generamba → реализуем базовый VIPER-модуль с тестами как образец → документируем правила для команды → при необходимости мигрируем приоритетные MVC/MVP-экраны.

Работа занимает 3–5 дней для нового проекта, включая генератор и документацию. Стоимость рассчитывается после анализа количества модулей и состава команды.